*/
/* CFApplicationPreferences.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: David Smith
*/
*/
/* CFArray.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
#include "CFInternal.h"
#include <string.h>
+
const CFArrayCallBacks kCFTypeArrayCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual};
static const CFArrayCallBacks __kCFNullArrayCallBacks = {0, NULL, NULL, NULL, NULL};
static void __CFArrayDeallocate(CFTypeRef cf) {
CFArrayRef array = (CFArrayRef)cf;
BEGIN_MUTATION(array);
+#if DEPLOYMENT_TARGET_MACOSX
// Under GC, keep contents alive when we know we can, either standard callbacks or NULL
// if (__CFBitfieldGetValue(cf->info, 5, 4)) return; // bits only ever set under GC
CFAllocatorRef allocator = __CFGetAllocator(array);
return;
}
}
+#endif
__CFArrayReleaseValues(array, CFRangeMake(0, __CFArrayGetCount(array)), true);
END_MUTATION(array);
}
#endif
CFIndex CFArrayGetCount(CFArrayRef array) {
- CF_OBJC_FUNCDISPATCH0(__kCFArrayTypeID, CFIndex, array, "count");
+ CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, CFIndex, (NSArray *)array, count);
__CFGenericValidateType(array, __kCFArrayTypeID);
CHECK_FOR_MUTATION(array);
return __CFArrayGetCount(array);
}
const void *CFArrayGetValueAtIndex(CFArrayRef array, CFIndex idx) {
- CF_OBJC_FUNCDISPATCH1(__kCFArrayTypeID, void *, array, "objectAtIndex:", idx);
+ CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, const void *, (NSArray *)array, objectAtIndex:idx);
__CFGenericValidateType(array, __kCFArrayTypeID);
CFAssert2(0 <= idx && idx < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx);
CHECK_FOR_MUTATION(array);
void CFArrayGetValues(CFArrayRef array, CFRange range, const void **values) {
- CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID, void, array, "getObjects:range:", values, range);
+ CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSArray *)array, getObjects:(id *)values range:NSMakeRange(range.location, range.length));
__CFGenericValidateType(array, __kCFArrayTypeID);
__CFArrayValidateRange(array, range, __PRETTY_FUNCTION__);
CFAssert1(NULL != values, __kCFLogAssertion, "%s(): pointer to values may not be NULL", __PRETTY_FUNCTION__);
}
void CFArrayAppendValue(CFMutableArrayRef array, const void *value) {
- CF_OBJC_FUNCDISPATCH1(__kCFArrayTypeID, void, array, "addObject:", value);
+ CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, addObject:(id)value);
+
__CFGenericValidateType(array, __kCFArrayTypeID);
CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
CHECK_FOR_MUTATION(array);
}
void CFArraySetValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void *value) {
- CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID, void, array, "setObject:atIndex:", value, idx);
+ CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, setObject:(id)value atIndex:(NSUInteger)idx);
__CFGenericValidateType(array, __kCFArrayTypeID);
CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
CFAssert2(0 <= idx && idx <= __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx);
}
void CFArrayInsertValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void *value) {
- CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID, void, array, "insertObject:atIndex:", value, idx);
+ CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, insertObject:(id)value atIndex:(NSUInteger)idx);
__CFGenericValidateType(array, __kCFArrayTypeID);
CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
CFAssert2(0 <= idx && idx <= __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx);
void CFArrayExchangeValuesAtIndices(CFMutableArrayRef array, CFIndex idx1, CFIndex idx2) {
const void *tmp;
struct __CFArrayBucket *bucket1, *bucket2;
- CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID, void, array, "exchangeObjectAtIndex:withObjectAtIndex:", idx1, idx2);
+ CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2);
__CFGenericValidateType(array, __kCFArrayTypeID);
CFAssert2(0 <= idx1 && idx1 < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index #1 (%d) out of bounds", __PRETTY_FUNCTION__, idx1);
CFAssert2(0 <= idx2 && idx2 < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index #2 (%d) out of bounds", __PRETTY_FUNCTION__, idx2);
}
void CFArrayRemoveValueAtIndex(CFMutableArrayRef array, CFIndex idx) {
- CF_OBJC_FUNCDISPATCH1(__kCFArrayTypeID, void, array, "removeObjectAtIndex:", idx);
+ CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, removeObjectAtIndex:(NSUInteger)idx);
__CFGenericValidateType(array, __kCFArrayTypeID);
CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
CFAssert2(0 <= idx && idx < __CFArrayGetCount(array), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx);
}
void CFArrayRemoveAllValues(CFMutableArrayRef array) {
- CF_OBJC_FUNCDISPATCH0(__kCFArrayTypeID, void, array, "removeAllObjects");
+ CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, removeAllObjects);
__CFGenericValidateType(array, __kCFArrayTypeID);
CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
CHECK_FOR_MUTATION(array);
void CFArrayReplaceValues(CFMutableArrayRef array, CFRange range, const void **newValues, CFIndex newCount) {
- CF_OBJC_FUNCDISPATCH3(__kCFArrayTypeID, void, array, "replaceObjectsInRange:withObjects:count:", range, (void **)newValues, newCount);
+ CF_OBJC_FUNCDISPATCHV(__kCFArrayTypeID, void, (NSMutableArray *)array, replaceObjectsInRange:NSMakeRange(range.location, range.length) withObjects:(id *)newValues count:(NSUInteger)newCount);
__CFGenericValidateType(array, __kCFArrayTypeID);
__CFArrayValidateRange(array, range, __PRETTY_FUNCTION__);
CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
Boolean immutable = false;
if (CF_IS_OBJC(__kCFArrayTypeID, array)) {
BOOL result;
- CF_OBJC_CALL1(BOOL, result, array, "isKindOfClass:", objc_lookUpClass("NSMutableArray"));
+ result = CF_OBJC_CALLV((NSMutableArray *)array, isKindOfClass:[NSMutableArray class]);
immutable = !result;
} else if (__kCFArrayImmutable == __CFArrayGetType(array)) {
immutable = true;
*/
/* CFArray.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
/*!
#include <CoreFoundation/CFBase.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
/*!
void CFArrayAppendArray(CFMutableArrayRef theArray, CFArrayRef otherArray, CFRange otherRange);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFARRAY__ */
*/
/* CFBag.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
Machine generated from Notes/HashingCode.template
*/
#include "CFBasicHash.h"
#include <CoreFoundation/CFString.h>
+
#define CFDictionary 0
#define CFSet 0
#define CFBag 0
} else {
newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0);
}
- if (!newcb) HALT;
+ if (!newcb) return NULL;
memmove(newcb, (void *)cb, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *));
return newcb;
}
} else {
newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0);
}
- if (!newcb) HALT;
+ if (!newcb) return NULL;
newcb->copyCallbacks = __CFBagCopyCallbacks;
newcb->freeCallbacks = __CFBagFreeCallbacks;
newcb->retainValue = __CFBagRetainValue;
}
CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb);
- CFBasicHashSetSpecialBits(ht, specialBits);
+ if (ht) CFBasicHashSetSpecialBits(ht, specialBits);
+ if (!ht && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, cb);
return ht;
}
CFTypeID typeID = CFBagGetTypeID();
CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
CFBasicHashRef ht = __CFBagCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
+ if (!ht) return NULL;
if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
for (CFIndex idx = 0; idx < numValues; idx++) {
CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
CFTypeID typeID = CFBagGetTypeID();
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);
if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (mutable)");
CFDictionaryGetKeysAndValues(other, klist, vlist);
#endif
ht = __CFBagCreateGeneric(allocator, & kCFTypeBagKeyCallBacks, CFDictionary ? & kCFTypeBagValueCallBacks : NULL, CFDictionary);
- if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
- for (CFIndex idx = 0; idx < numValues; idx++) {
+ if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+ for (CFIndex idx = 0; ht && idx < numValues; idx++) {
CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
}
if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
} else {
ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
}
+ if (!ht) return NULL;
CFBasicHashMakeImmutable(ht);
*(uintptr_t *)ht = __CFISAForTypeID(typeID);
_CFRuntimeSetInstanceTypeID(ht, typeID);
CFDictionaryGetKeysAndValues(other, klist, vlist);
#endif
ht = __CFBagCreateGeneric(allocator, & kCFTypeBagKeyCallBacks, CFDictionary ? & kCFTypeBagValueCallBacks : NULL, CFDictionary);
- if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
- for (CFIndex idx = 0; idx < numValues; idx++) {
+ if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+ for (CFIndex idx = 0; ht && idx < numValues; idx++) {
CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
}
if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
} else {
ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
}
+ if (!ht) return NULL;
*(uintptr_t *)ht = __CFISAForTypeID(typeID);
_CFRuntimeSetInstanceTypeID(ht, typeID);
if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (mutable)");
}
CFIndex CFBagGetCount(CFHashRef hc) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFBagTypeID, CFIndex, hc, "count");
- if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFBagTypeID, CFIndex, hc, "count");
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, CFIndex, (NSDictionary *)hc, count);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, CFIndex, (NSSet *)hc, count);
__CFGenericValidateType(hc, __kCFBagTypeID);
return CFBasicHashGetCount((CFBasicHashRef)hc);
}
#if CFSet || CFBag
CFIndex CFBagGetCountOfValue(CFHashRef hc, const_any_pointer_t key) {
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, CFIndex, hc, "countForKey:", key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, CFIndex, hc, "countForObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, CFIndex, (NSDictionary *)hc, countForKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, CFIndex, (NSSet *)hc, countForObject:(id)key);
__CFGenericValidateType(hc, __kCFBagTypeID);
return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key);
}
#if CFSet || CFBag
Boolean CFBagContainsValue(CFHashRef hc, const_any_pointer_t key) {
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, char, hc, "containsKey:", key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, char, hc, "containsObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, char, (NSDictionary *)hc, containsKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, char, (NSSet *)hc, containsObject:(id)key);
__CFGenericValidateType(hc, __kCFBagTypeID);
return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key));
}
const_any_pointer_t CFBagGetValue(CFHashRef hc, const_any_pointer_t key) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, const_any_pointer_t, hc, "objectForKey:", key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, const_any_pointer_t, hc, "member:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, const_any_pointer_t, (NSSet *)hc, member:(id)key);
__CFGenericValidateType(hc, __kCFBagTypeID);
CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0);
}
Boolean CFBagGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, Boolean, hc, "__getValue:forKey:", (any_t *)value, key);
- if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, Boolean, hc, "__getValue:forObj:", (any_t *)value, key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key);
__CFGenericValidateType(hc, __kCFBagTypeID);
CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
if (0 < bkt.count) {
#if CFDictionary
CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
- CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, CFIndex, hc, "countForObject:", value);
+ CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, CFIndex, (NSDictionary *)hc, countForObject:(id)value);
__CFGenericValidateType(hc, __kCFBagTypeID);
return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value);
}
Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) {
- CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, char, hc, "containsObject:", value);
+ CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, char, (NSDictionary *)hc, containsObject:(id)value);
__CFGenericValidateType(hc, __kCFBagTypeID);
return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value));
}
CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
- CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, Boolean, hc, "getActualKey:forKey:", actualkey, key);
__CFGenericValidateType(hc, __kCFBagTypeID);
CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
if (0 < bkt.count) {
void CFBagGetValues(CFHashRef hc, const_any_pointer_t *keybuf) {
const_any_pointer_t *valuebuf = 0;
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "getObjects:andKeys:", (any_t *)valuebuf, (any_t *)keybuf);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "getObjects:", (any_t *)keybuf);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSSet *)hc, getObjects:(id *)keybuf);
__CFGenericValidateType(hc, __kCFBagTypeID);
if (kCFUseCollectableAllocator) {
CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc);
void CFBagApplyFunction(CFHashRef hc, CFBagApplierFunction applier, any_pointer_t context) {
FAULT_CALLBACK((void **)&(applier));
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "__apply:context:", applier, context);
- if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "__applyValues:context:", applier, context);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSDictionary *)hc, __apply:(void (*)(const void *, const void *, void *))applier context:(void *)context);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context);
__CFGenericValidateType(hc, __kCFBagTypeID);
CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
#if CFDictionary
void CFBagAddValue(CFMutableHashRef hc, const_any_pointer_t key) {
const_any_pointer_t value = key;
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "addObject:forKey:", value, key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "addObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableSet *)hc, addObject:(id)key);
__CFGenericValidateType(hc, __kCFBagTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
void CFBagReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) {
const_any_pointer_t value = key;
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "replaceObject:forKey:", value, key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "replaceObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableDictionary *)hc, replaceObject:(id)value forKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableSet *)hc, replaceObject:(id)key);
__CFGenericValidateType(hc, __kCFBagTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
void CFBagSetValue(CFMutableHashRef hc, const_any_pointer_t key) {
const_any_pointer_t value = key;
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "setObject:forKey:", value, key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "setObject:", 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);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
}
void CFBagRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "removeObjectForKey:", key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "removeObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableSet *)hc, removeObject:(id)key);
__CFGenericValidateType(hc, __kCFBagTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
}
void CFBagRemoveAllValues(CFMutableHashRef hc) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFBagTypeID, void, hc, "removeAllObjects");
- if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFBagTypeID, void, hc, "removeAllObjects");
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableDictionary *)hc, removeAllObjects);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFBagTypeID, void, (NSMutableSet *)hc, removeAllObjects);
__CFGenericValidateType(hc, __kCFBagTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
*/
/* CFBag.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFBAG__)
#include <CoreFoundation/CFBase.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
typedef const void * (*CFBagRetainCallBack)(CFAllocatorRef allocator, const void *value);
void CFBagRemoveAllValues(CFMutableBagRef theBag);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFBAG__ */
*/
/* CFBase.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
#include <CoreFoundation/CFBase.h>
#include "CFInternal.h"
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
- #include <pthread.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#include <pthread.h>
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
- #include <malloc/malloc.h>
- extern size_t malloc_good_size(size_t size);
- #include <mach/mach.h>
- #include <dlfcn.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
+#include <malloc/malloc.h>
+#include <mach/mach.h>
+#include <dlfcn.h>
#endif
#include <stdlib.h>
#include <string.h>
// -------- -------- -------- -------- -------- -------- -------- --------
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-// CFAllocator structure must match struct _malloc_zone_t!
-// The first two reserved fields in struct _malloc_zone_t are for us with CFRuntimeBase
-#endif
-
-
struct __CFAllocator {
CFRuntimeBase _base;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
+ // CFAllocator structure must match struct _malloc_zone_t!
+ // The first two reserved fields in struct _malloc_zone_t are for us with CFRuntimeBase
size_t (*size)(struct _malloc_zone_t *zone, const void *ptr); /* returns the size of a block or 0 if not in this zone; must be fast, especially for negative answers */
void *(*malloc)(struct _malloc_zone_t *zone, size_t size);
void *(*calloc)(struct _malloc_zone_t *zone, size_t num_items, size_t size); /* same as malloc, but block returned is set to zero */
return retval;
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
__private_extern__ void __CFAllocatorDeallocate(CFTypeRef cf);
malloc_zone_free(info, ptr);
}
-#endif
+#else
-#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
static void *__CFAllocatorSystemAllocate(CFIndex size, CFOptionFlags hint, void *info) {
return malloc(size);
}
static struct __CFAllocator __kCFAllocatorMalloc = {
INIT_CFRUNTIME_BASE(),
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
__CFAllocatorCustomSize,
__CFAllocatorCustomMalloc,
__CFAllocatorCustomCalloc,
static struct __CFAllocator __kCFAllocatorMallocZone = {
INIT_CFRUNTIME_BASE(),
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
__CFAllocatorCustomSize,
__CFAllocatorCustomMalloc,
__CFAllocatorCustomCalloc,
static struct __CFAllocator __kCFAllocatorSystemDefault = {
INIT_CFRUNTIME_BASE(),
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
__CFAllocatorCustomSize,
__CFAllocatorCustomMalloc,
__CFAllocatorCustomCalloc,
static struct __CFAllocator __kCFAllocatorNull = {
INIT_CFRUNTIME_BASE(),
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
__CFAllocatorNullSize,
__CFAllocatorNullMalloc,
__CFAllocatorNullCalloc,
_CFRuntimeSetInstanceTypeID(&__kCFAllocatorSystemDefault, __kCFAllocatorTypeID);
__kCFAllocatorSystemDefault._base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
__kCFAllocatorSystemDefault._context.info = (kCFUseCollectableAllocator ? objc_collectableZone() : malloc_default_zone());
#endif
__kCFAllocatorSystemDefault._allocator = kCFAllocatorSystemDefault;
__kCFAllocatorMalloc._base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID);
__kCFAllocatorMalloc._allocator = kCFAllocatorSystemDefault;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
- _CFRuntimeSetInstanceTypeID(&__kCFAllocatorMallocZone, __kCFAllocatorTypeID);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
+ _CFRuntimeSetInstanceTypeID(&__kCFAllocatorMallocZone, __kCFAllocatorTypeID);
__kCFAllocatorMallocZone._base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID);
__kCFAllocatorMallocZone._allocator = kCFAllocatorSystemDefault;
__kCFAllocatorMallocZone._context.info = malloc_default_zone();
__CFGenericValidateType(allocator, __kCFAllocatorTypeID);
}
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (allocator && allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
return; // require allocator to this function to be an allocator
}
CFAllocatorRetainCallBack retainFunc;
CFAllocatorAllocateCallBack allocateFunc;
void *retainedInfo;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (allocator && kCFAllocatorUseContext != allocator && allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
return NULL; // require allocator to this function to be an allocator
}
memory->_base._cfinfo[CF_INFO_BITS] = 0;
_CFRuntimeSetInstanceTypeID(memory, __kCFAllocatorTypeID);
memory->_base._cfisa = __CFISAForTypeID(__kCFAllocatorTypeID);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
memory->size = __CFAllocatorCustomSize;
memory->malloc = __CFAllocatorCustomMalloc;
memory->calloc = __CFAllocatorCustomCalloc;
allocator = __CFGetDefaultAllocator();
}
-#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
+#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
__CFGenericValidateType(allocator, __kCFAllocatorTypeID);
}
__CFGenericValidateType(allocator, __kCFAllocatorTypeID);
#endif
if (0 == size) return NULL;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
return malloc_zone_malloc((malloc_zone_t *)allocator, size);
}
allocator = __CFGetDefaultAllocator();
}
-#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
+#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
__CFGenericValidateType(allocator, __kCFAllocatorTypeID);
}
__CFGenericValidateType(allocator, __kCFAllocatorTypeID);
#endif
if (NULL == ptr && 0 < newsize) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
return malloc_zone_malloc((malloc_zone_t *)allocator, newsize);
}
return newptr;
}
if (NULL != ptr && 0 == newsize) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
#if defined(DEBUG)
size_t size = malloc_size(ptr);
return NULL;
}
if (NULL == ptr && 0 == newsize) return NULL;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
return malloc_zone_realloc((malloc_zone_t *)allocator, ptr, newsize);
}
allocator = __CFGetDefaultAllocator();
}
-#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
+#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
__CFGenericValidateType(allocator, __kCFAllocatorTypeID);
}
#else
__CFGenericValidateType(allocator, __kCFAllocatorTypeID);
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
#if defined(DEBUG)
size_t size = malloc_size(ptr);
allocator = __CFGetDefaultAllocator();
}
-#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
+#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
__CFGenericValidateType(allocator, __kCFAllocatorTypeID);
}
#else
__CFGenericValidateType(allocator, __kCFAllocatorTypeID);
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
return malloc_good_size(size);
}
allocator = __CFGetDefaultAllocator();
}
-#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
+#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI)
if (allocator->_base._cfisa == __CFISAForTypeID(__kCFAllocatorTypeID)) {
__CFGenericValidateType(allocator, __kCFAllocatorTypeID);
}
__CFGenericValidateType(allocator, __kCFAllocatorTypeID);
#endif
CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (allocator->_base._cfisa != __CFISAForTypeID(__kCFAllocatorTypeID)) { // malloc_zone_t *
return;
}
context->reallocate = __CFAllocatorGetReallocateFunction(&allocator->_context);
context->deallocate = __CFAllocatorGetDeallocateFunction(&allocator->_context);
context->preferredSize = __CFAllocatorGetPreferredSizeFunction(&allocator->_context);
-#if SUPPORT_CFM
- context->retain = (void *)((uintptr_t)context->retain & ~0x3);
- context->release = (void *)((uintptr_t)context->release & ~0x3);
- context->copyDescription = (void *)((uintptr_t)context->copyDescription & ~0x3);
- context->allocate = (void *)((uintptr_t)context->allocate & ~0x3);
- context->reallocate = (void *)((uintptr_t)context->reallocate & ~0x3);
- context->deallocate = (void *)((uintptr_t)context->deallocate & ~0x3);
- context->preferredSize = (void *)((uintptr_t)context->preferredSize & ~0x3);
-#endif
}
__private_extern__ void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint)
void CFCollection_non_gc_storage_error(void) { }
-#if !SUPPORT_CFM
-void _CFRuntimeSetCFMPresent(void *addr) {
-}
-#endif
-
-#if SUPPORT_CFM
-
-static int hasCFM = 0;
-
void _CFRuntimeSetCFMPresent(void *addr) {
- hasCFM = 1;
}
-/* See comments below */
-__private_extern__ void __CF_FAULT_CALLBACK(void **ptr) {
- uintptr_t p = (uintptr_t)*ptr;
- if ((0 == p) || (p & 0x1)) return;
- if (0 == hasCFM || (0x90000000 <= p && p < 0xA0000000)) {
- *ptr = (void *)(p | 0x1);
- } else {
- uintptr_t known = ~0;
- Dl_info info;
- known = dladdr((void *)p, &info);
- *ptr = (void *)(p | (known ? 0x1 : 0x3));
- }
-}
-
-/*
-Jump to callback function. r2 is not saved and restored
-in the jump-to-CFM case, since we assume that dyld code
-never uses that register and that CF is dyld.
-
-There are three states for (ptr & 0x3):
- 0b00: check not yet done (or not going to be done, and is a dyld func ptr)
- 0b01: check done, dyld function pointer
- 0b11: check done, CFM tvector pointer
-(but a NULL callback just stays NULL)
-
-There may be up to 5 word-sized arguments. Floating point
-arguments can be done, but count as two word arguments.
-Return value can be integral or real.
-*/
-
-/* Keep this assembly at the bottom of the source file! */
-
-__asm__ (
-".text\n"
-" .align 2\n"
-".private_extern ___CF_INVOKE_CALLBACK\n"
-"___CF_INVOKE_CALLBACK:\n"
- "rlwinm r12,r3,0,0,29\n"
- "andi. r0,r3,0x2\n"
- "or r3,r4,r4\n"
- "or r4,r5,r5\n"
- "or r5,r6,r6\n"
- "or r6,r7,r7\n"
- "or r7,r8,r8\n"
- "beq- Lcall\n"
- "lwz r2,0x4(r12)\n"
- "lwz r12,0x0(r12)\n"
-"Lcall: mtspr ctr,r12\n"
- "bctr\n");
-
-#endif
-
// void __HALT(void);
*/
/* CFBase.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFBASE__)
#define __WIN32__ 1
#endif
+#if defined(_WIN64) && !defined(__WIN64__)
+#define __WIN64__ 1
+#endif
+
+#if defined(__WIN64__) && !defined(__LLP64__)
+#define __LLP64__ 1
+#endif
+
#if defined(_MSC_VER) && defined(_M_IX86)
#define __i386__ 1
#endif
#define __has_feature(x) 0
#endif
+// Some compilers provide the capability to test if certain attributes are available. This macro provides a compatibility path for other compilers.
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
+#ifndef __has_extension
+#define __has_extension(x) 0
+#endif
+
#if defined(__GNUC__) || TARGET_OS_WIN32
#include <stdint.h>
#include <stdbool.h>
#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)
+#if (TARGET_OS_MAC || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
#include <AvailabilityMacros.h>
#include <Availability.h>
+#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) AVAILABLE_MAC_OS_X_VERSION_##_mac##_AND_LATER
+#define CF_AVAILABLE(_mac, _ios) __OSX_AVAILABLE_STARTING(__MAC_##_mac, __IPHONE_##_ios)
// Available on MacOS only
-#define CF_AVAILABLE_MAC(_mac) AVAILABLE_MAC_OS_X_VERSION_##_mac##_AND_LATER
+#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) AVAILABLE_MAC_OS_X_VERSION_##_macIntro##_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_##_macDep
+#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) AVAILABLE_MAC_OS_X_VERSION_##_macIntro##_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_##_macDep
+#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)
-#elif (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
-#include <AvailabilityMacros.h>
-#include <Availability.h>
-
-#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)
-
#else
#if TARGET_OS_WIN32
#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_INLINE static __inline__ __attribute__((always_inline))
#elif defined(__GNUC__)
#define CF_INLINE static __inline__
- #elif defined(__MWERKS__) || defined(__cplusplus)
+ #elif defined(__cplusplus)
#define CF_INLINE static inline
#elif defined(_MSC_VER)
#define CF_INLINE static __inline
// Marks functions which return a CF type that needs to be released by the caller but whose names are not consistent with CoreFoundation naming rules. The recommended fix to this is to rename the functions, but this macro can be used to let the clang static analyzer know of any exceptions that cannot be fixed.
// This macro is ONLY to be used in exceptional circumstances, not to annotate functions which conform to the CoreFoundation naming rules.
+#ifndef CF_RETURNS_RETAINED
#if __has_feature(attribute_cf_returns_retained)
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
#else
#define CF_RETURNS_RETAINED
#endif
+#endif
// Marks functions which return a CF type that may need to be retained by the caller but whose names are not consistent with CoreFoundation naming rules. The recommended fix to this is to rename the functions, but this macro can be used to let the clang static analyzer know of any exceptions that cannot be fixed.
// This macro is ONLY to be used in exceptional circumstances, not to annotate functions which conform to the CoreFoundation naming rules.
+#ifndef CF_RETURNS_NOT_RETAINED
#if __has_feature(attribute_cf_returns_not_retained)
#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
#else
#define CF_RETURNS_NOT_RETAINED
#endif
+#endif
+
+// Marks function arguments which are released by the callee.
+#ifndef CF_RELEASES_ARGUMENT
+#if __has_feature(attribute_cf_consumed)
+#define CF_RELEASES_ARGUMENT __attribute__((cf_consumed))
+#else
+#define CF_RELEASES_ARGUMENT
+#endif
+#endif
+
+// Compatibility
+#ifndef CF_CONSUMED
+#if __has_feature(attribute_cf_consumed)
+#define CF_CONSUMED __attribute__((cf_consumed))
+#else
+#define CF_CONSUMED
+#endif
+#endif
// Marks functions which cannot be used when compiling in automatic reference counting mode.
#if __has_feature(objc_arc)
#define CF_AUTOMATED_REFCOUNT_UNAVAILABLE
#endif
+#ifndef CF_IMPLICIT_BRIDGING_ENABLED
+#if __has_feature(arc_cf_code_audited)
+#define CF_IMPLICIT_BRIDGING_ENABLED _Pragma("clang arc_cf_code_audited begin")
+#else
+#define CF_IMPLICIT_BRIDGING_ENABLED
+#endif
+#endif
+
+#ifndef CF_IMPLICIT_BRIDGING_DISABLED
+#if __has_feature(arc_cf_code_audited)
+#define CF_IMPLICIT_BRIDGING_DISABLED _Pragma("clang arc_cf_code_audited end")
+#else
+#define CF_IMPLICIT_BRIDGING_DISABLED
+#endif
+#endif
+
+
CF_EXPORT double kCFCoreFoundationVersionNumber;
#if TARGET_OS_MAC
#define kCFCoreFoundationVersionNumber10_6_3 550.19
#define kCFCoreFoundationVersionNumber10_6_4 550.29
#define kCFCoreFoundationVersionNumber10_6_5 550.42
+#define kCFCoreFoundationVersionNumber10_6_6 550.42
+#define kCFCoreFoundationVersionNumber10_6_7 550.42
+#define kCFCoreFoundationVersionNumber10_6_8 550.43
+#define kCFCoreFoundationVersionNumber10_7 635.00
+#define kCFCoreFoundationVersionNumber10_7_1 635.00
+#define kCFCoreFoundationVersionNumber10_7_2 635.15
+#define kCFCoreFoundationVersionNumber10_7_3 635.19
+#define kCFCoreFoundationVersionNumber10_7_4 635.21
#endif
#if TARGET_OS_IPHONE
#define kCFCoreFoundationVersionNumber_iOS_4_0 550.32
#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
#endif
+#if __LLP64__
+typedef unsigned long long CFTypeID;
+typedef unsigned long long CFOptionFlags;
+typedef unsigned long long CFHashCode;
+typedef signed long long CFIndex;
+#else
typedef unsigned long CFTypeID;
typedef unsigned long CFOptionFlags;
typedef unsigned long CFHashCode;
typedef signed long CFIndex;
+#endif
/* Base "type" of all "CF objects", and polymorphic functions on them */
typedef const void * CFTypeRef;
typedef CFTypeRef CFPropertyListRef;
/* Values returned from comparison functions */
-enum {
- kCFCompareLessThan = -1,
+typedef CF_ENUM(CFIndex, CFComparisonResult) {
+ kCFCompareLessThan = -1L,
kCFCompareEqualTo = 0,
kCFCompareGreaterThan = 1
};
-typedef CFIndex CFComparisonResult;
/* A standard comparison function */
typedef CFComparisonResult (*CFComparatorFunction)(const void *val1, const void *val2, void *context);
--- /dev/null
+/*
+ * Copyright (c) 2012 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@
+ */
+
+/* CFBasicHash.m
+ Copyright (c) 2008-2012, Apple Inc. All rights reserved.
+ Responsibility: Christopher Kane
+*/
+
+#import "CFBasicHash.h"
+#import <CoreFoundation/CFRuntime.h>
+#import <CoreFoundation/CFSet.h>
+#import <Block.h>
+#import <math.h>
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#define __SetLastAllocationEventName(A, B) do { if (__CFOASafe && (A)) __CFSetLastAllocationEventName(A, B); } while (0)
+#else
+#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
+#define ENABLE_MEMORY_COUNTERS 0
+
+#if defined(DTRACE_PROBES_DISABLED) && DTRACE_PROBES_DISABLED
+#undef ENABLE_DTRACE_PROBES
+#define ENABLE_DTRACE_PROBES 0
+#endif
+
+/*
+// dtrace -h -s foo.d
+// Note: output then changed by casts of the arguments
+// dtrace macros last generated 2010-09-08 on 10.7 prerelease (11A259)
+
+provider Cocoa_HashTable {
+ probe hash_key(unsigned long table, unsigned long key, unsigned long hash);
+ probe test_equal(unsigned long table, unsigned long key1, unsigned long key2);
+ probe probing_start(unsigned long table, unsigned long num_buckets);
+ probe probe_empty(unsigned long table, unsigned long idx);
+ probe probe_deleted(unsigned long table, unsigned long idx);
+ probe probe_valid(unsigned long table, unsigned long idx);
+ probe probing_end(unsigned long table, unsigned long num_probes);
+ probe rehash_start(unsigned long table, unsigned long num_buckets, unsigned long total_size);
+ probe rehash_end(unsigned long table, unsigned long num_buckets, unsigned long total_size);
+};
+
+#pragma D attributes Unstable/Unstable/Common provider Cocoa_HashTable provider
+#pragma D attributes Private/Private/Unknown provider Cocoa_HashTable module
+#pragma D attributes Private/Private/Unknown provider Cocoa_HashTable function
+#pragma D attributes Unstable/Unstable/Common provider Cocoa_HashTable name
+#pragma D attributes Unstable/Unstable/Common provider Cocoa_HashTable args
+*/
+
+#if ENABLE_DTRACE_PROBES
+
+#define COCOA_HASHTABLE_STABILITY "___dtrace_stability$Cocoa_HashTable$v1$4_4_5_1_1_0_1_1_0_4_4_5_4_4_5"
+
+#define COCOA_HASHTABLE_TYPEDEFS "___dtrace_typedefs$Cocoa_HashTable$v2"
+
+#define COCOA_HASHTABLE_REHASH_END(arg0, arg1, arg2) \
+do { \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+ __dtrace_probe$Cocoa_HashTable$rehash_end$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1), (unsigned long)(arg2)); \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_REHASH_END_ENABLED() \
+ ({ int _r = __dtrace_isenabled$Cocoa_HashTable$rehash_end$v1(); \
+ __asm__ volatile(""); \
+ _r; })
+#define COCOA_HASHTABLE_REHASH_START(arg0, arg1, arg2) \
+do { \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+ __dtrace_probe$Cocoa_HashTable$rehash_start$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1), (unsigned long)(arg2)); \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_REHASH_START_ENABLED() \
+ ({ int _r = __dtrace_isenabled$Cocoa_HashTable$rehash_start$v1(); \
+ __asm__ volatile(""); \
+ _r; })
+#define COCOA_HASHTABLE_HASH_KEY(arg0, arg1, arg2) \
+do { \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+ __dtrace_probe$Cocoa_HashTable$hash_key$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1), (unsigned long)(arg2)); \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_HASH_KEY_ENABLED() \
+ ({ int _r = __dtrace_isenabled$Cocoa_HashTable$hash_key$v1(); \
+ __asm__ volatile(""); \
+ _r; })
+#define COCOA_HASHTABLE_PROBE_DELETED(arg0, arg1) \
+do { \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+ __dtrace_probe$Cocoa_HashTable$probe_deleted$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_PROBE_DELETED_ENABLED() \
+ ({ int _r = __dtrace_isenabled$Cocoa_HashTable$probe_deleted$v1(); \
+ __asm__ volatile(""); \
+ _r; })
+#define COCOA_HASHTABLE_PROBE_EMPTY(arg0, arg1) \
+do { \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+ __dtrace_probe$Cocoa_HashTable$probe_empty$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_PROBE_EMPTY_ENABLED() \
+ ({ int _r = __dtrace_isenabled$Cocoa_HashTable$probe_empty$v1(); \
+ __asm__ volatile(""); \
+ _r; })
+#define COCOA_HASHTABLE_PROBE_VALID(arg0, arg1) \
+do { \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+ __dtrace_probe$Cocoa_HashTable$probe_valid$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_PROBE_VALID_ENABLED() \
+ ({ int _r = __dtrace_isenabled$Cocoa_HashTable$probe_valid$v1(); \
+ __asm__ volatile(""); \
+ _r; })
+#define COCOA_HASHTABLE_PROBING_END(arg0, arg1) \
+do { \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+ __dtrace_probe$Cocoa_HashTable$probing_end$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_PROBING_END_ENABLED() \
+ ({ int _r = __dtrace_isenabled$Cocoa_HashTable$probing_end$v1(); \
+ __asm__ volatile(""); \
+ _r; })
+#define COCOA_HASHTABLE_PROBING_START(arg0, arg1) \
+do { \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+ __dtrace_probe$Cocoa_HashTable$probing_start$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_PROBING_START_ENABLED() \
+ ({ int _r = __dtrace_isenabled$Cocoa_HashTable$probing_start$v1(); \
+ __asm__ volatile(""); \
+ _r; })
+#define COCOA_HASHTABLE_TEST_EQUAL(arg0, arg1, arg2) \
+do { \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
+ __dtrace_probe$Cocoa_HashTable$test_equal$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1), (unsigned long)(arg2)); \
+ __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
+} while (0)
+#define COCOA_HASHTABLE_TEST_EQUAL_ENABLED() \
+ ({ int _r = __dtrace_isenabled$Cocoa_HashTable$test_equal$v1(); \
+ __asm__ volatile(""); \
+ _r; })
+
+extern void __dtrace_probe$Cocoa_HashTable$hash_key$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$hash_key$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$probe_deleted$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$probe_deleted$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$probe_empty$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$probe_empty$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$probe_valid$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$probe_valid$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$probing_end$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$probing_end$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$probing_start$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$probing_start$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$rehash_end$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$rehash_end$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$rehash_start$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$rehash_start$v1(void);
+extern void __dtrace_probe$Cocoa_HashTable$test_equal$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long, unsigned long);
+extern int __dtrace_isenabled$Cocoa_HashTable$test_equal$v1(void);
+
+#else
+
+#define COCOA_HASHTABLE_REHASH_END(arg0, arg1, arg2) do {} while (0)
+#define COCOA_HASHTABLE_REHASH_END_ENABLED() 0
+#define COCOA_HASHTABLE_REHASH_START(arg0, arg1, arg2) do {} while (0)
+#define COCOA_HASHTABLE_REHASH_START_ENABLED() 0
+#define COCOA_HASHTABLE_HASH_KEY(arg0, arg1, arg2) do {} while (0)
+#define COCOA_HASHTABLE_HASH_KEY_ENABLED() 0
+#define COCOA_HASHTABLE_PROBE_DELETED(arg0, arg1) do {} while (0)
+#define COCOA_HASHTABLE_PROBE_DELETED_ENABLED() 0
+#define COCOA_HASHTABLE_PROBE_EMPTY(arg0, arg1) do {} while (0)
+#define COCOA_HASHTABLE_PROBE_EMPTY_ENABLED() 0
+#define COCOA_HASHTABLE_PROBE_VALID(arg0, arg1) do {} while (0)
+#define COCOA_HASHTABLE_PROBE_VALID_ENABLED() 0
+#define COCOA_HASHTABLE_PROBING_END(arg0, arg1) do {} while (0)
+#define COCOA_HASHTABLE_PROBING_END_ENABLED() 0
+#define COCOA_HASHTABLE_PROBING_START(arg0, arg1) do {} while (0)
+#define COCOA_HASHTABLE_PROBING_START_ENABLED() 0
+#define COCOA_HASHTABLE_TEST_EQUAL(arg0, arg1, arg2) do {} while (0)
+#define COCOA_HASHTABLE_TEST_EQUAL_ENABLED() 0
+
+#endif
+
+
+#if !defined(__LP64__)
+#define __LP64__ 0
+#endif
+
+// Prime numbers. Values above 100 have been adjusted up so that the
+// malloced block size will be just below a multiple of 512; values
+// above 1200 have been adjusted up to just below a multiple of 4096.
+static const uintptr_t __CFBasicHashTableSizes[64] = {
+ 0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723,
+ 2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607,
+ 214519, 346607, 561109, 907759, 1468927, 2376191, 3845119,
+ 6221311, 10066421, 16287743, 26354171, 42641881, 68996069,
+ 111638519, 180634607, 292272623, 472907251,
+#if __LP64__
+ 765180413UL, 1238087663UL, 2003267557UL, 3241355263UL, 5244622819UL,
+#if 0
+ 8485977589UL, 13730600407UL, 22216578047UL, 35947178479UL,
+ 58163756537UL, 94110934997UL, 152274691561UL, 246385626107UL,
+ 398660317687UL, 645045943807UL, 1043706260983UL, 1688752204787UL,
+ 2732458465769UL, 4421210670577UL, 7153669136377UL,
+ 11574879807461UL, 18728548943849UL, 30303428750843UL
+#endif
+#endif
+};
+
+static const uintptr_t __CFBasicHashTableCapacities[64] = {
+ 0, 3, 6, 11, 19, 32, 52, 85, 118, 155, 237, 390, 672, 1065,
+ 1732, 2795, 4543, 7391, 12019, 19302, 31324, 50629, 81956,
+ 132580, 214215, 346784, 561026, 907847, 1468567, 2376414,
+ 3844982, 6221390, 10066379, 16287773, 26354132, 42641916,
+ 68996399, 111638327, 180634415, 292272755,
+#if __LP64__
+ 472907503UL, 765180257UL, 1238087439UL, 2003267722UL, 3241355160UL,
+#if 0
+ 5244622578UL, 8485977737UL, 13730600347UL, 22216578100UL,
+ 35947178453UL, 58163756541UL, 94110935011UL, 152274691274UL,
+ 246385626296UL, 398660317578UL, 645045943559UL, 1043706261135UL,
+ 1688752204693UL, 2732458465840UL, 4421210670552UL,
+ 7153669136706UL, 11574879807265UL, 18728548943682UL
+#endif
+#endif
+};
+
+// Primitive roots for the primes above
+static const uintptr_t __CFBasicHashPrimitiveRoots[64] = {
+ 0, 2, 3, 2, 5, 6, 7, 3, 19, 6, 5, 3, 3, 3,
+ 2, 5, 6, 3, 3, 6, 2, 3, 3,
+ 3, 5, 10, 3, 3, 22, 3,
+ 3, 3, 5, 2, 22, 2,
+ 11, 5, 5, 2,
+#if __LP64__
+ 3, 10, 2, 3, 10,
+ 2, 3, 5, 3,
+ 3, 2, 7, 2,
+ 3, 3, 3, 2,
+ 3, 5, 5,
+ 2, 3, 2
+#endif
+};
+
+CF_INLINE void *__CFBasicHashAllocateMemory(CFConstBasicHashRef ht, CFIndex count, CFIndex elem_size, Boolean strong, Boolean compactable) {
+ CFAllocatorRef allocator = CFGetAllocator(ht);
+ void *new_mem = NULL;
+ if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+ new_mem = auto_zone_allocate_object(objc_collectableZone(), count * elem_size, strong ? (compactable ? AUTO_POINTERS_ONLY : AUTO_MEMORY_SCANNED) : AUTO_UNSCANNED, false, false);
+ } else {
+ new_mem = CFAllocatorAllocate(allocator, count * elem_size, 0);
+ }
+ return new_mem;
+}
+
+CF_INLINE void *__CFBasicHashAllocateMemory2(CFAllocatorRef allocator, CFIndex count, CFIndex elem_size, Boolean strong, Boolean compactable) {
+ void *new_mem = NULL;
+ if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+ new_mem = auto_zone_allocate_object(objc_collectableZone(), count * elem_size, strong ? (compactable ? AUTO_POINTERS_ONLY : AUTO_MEMORY_SCANNED) : AUTO_UNSCANNED, false, false);
+ } else {
+ new_mem = CFAllocatorAllocate(allocator, count * elem_size, 0);
+ }
+ return new_mem;
+}
+
+#define __CFBasicHashSubABZero 0xa7baadb1
+#define __CFBasicHashSubABOne 0xa5baadb9
+
+typedef union {
+ uintptr_t neutral;
+ id strong;
+ id weak;
+} CFBasicHashValue;
+
+struct __CFBasicHash {
+ CFRuntimeBase base;
+ struct { // 128 bits
+ 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;
+ uint8_t hashes_offset:2;
+ uint8_t strong_values:1;
+ uint8_t strong_keys:1;
+ uint8_t weak_values:1;
+ uint8_t weak_keys:1;
+ 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;
+ } 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
+}
+
+__private_extern__ Boolean CFBasicHashHasStrongKeys(CFConstBasicHashRef ht) {
+#if DEPLOYMENT_TARGET_MACOSX
+ return ht->bits.strong_keys ? true : false;
+#else
+ return false;
+#endif
+}
+
+CF_INLINE Boolean __CFBasicHashHasCompactableKeys(CFConstBasicHashRef ht) {
+#if DEPLOYMENT_TARGET_MACOSX
+ return ht->bits.compactable_keys ? true : false;
+#else
+ return false;
+#endif
+}
+
+CF_INLINE Boolean __CFBasicHashHasCompactableValues(CFConstBasicHashRef ht) {
+#if DEPLOYMENT_TARGET_MACOSX
+ return ht->bits.compactable_values ? true : false;
+#else
+ return false;
+#endif
+}
+
+CF_INLINE Boolean __CFBasicHashHasWeakValues(CFConstBasicHashRef ht) {
+#if DEPLOYMENT_TARGET_MACOSX
+ return ht->bits.weak_values ? true : false;
+#else
+ return false;
+#endif
+}
+
+CF_INLINE Boolean __CFBasicHashHasWeakKeys(CFConstBasicHashRef ht) {
+#if DEPLOYMENT_TARGET_MACOSX
+ return ht->bits.weak_keys ? true : false;
+#else
+ return false;
+#endif
+}
+
+CF_INLINE Boolean __CFBasicHashHasHashCache(CFConstBasicHashRef ht) {
+#if DEPLOYMENT_TARGET_MACOSX
+ return ht->bits.hashes_offset ? true : false;
+#else
+ return false;
+#endif
+}
+
+CF_INLINE uintptr_t __CFBasicHashImportValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
+ return ht->callbacks->retainValue(ht, stack_value);
+}
+
+CF_INLINE uintptr_t __CFBasicHashImportKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ return ht->callbacks->retainKey(ht, stack_key);
+}
+
+CF_INLINE void __CFBasicHashEjectValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
+ ht->callbacks->releaseValue(ht, stack_value);
+}
+
+CF_INLINE void __CFBasicHashEjectKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ ht->callbacks->releaseKey(ht, 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);
+}
+
+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);
+}
+
+CF_INLINE CFHashCode __CFBasicHashHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ CFHashCode hash_code = (CFHashCode)ht->callbacks->hashKey(ht, stack_key);
+ COCOA_HASHTABLE_HASH_KEY(ht, stack_key, hash_code);
+ return hash_code;
+}
+
+CF_INLINE CFBasicHashValue *__CFBasicHashGetValues(CFConstBasicHashRef ht) {
+ return (CFBasicHashValue *)ht->pointers[0];
+}
+
+CF_INLINE void __CFBasicHashSetValues(CFBasicHashRef ht, CFBasicHashValue *ptr) {
+ __AssignWithWriteBarrier(&ht->pointers[0], ptr);
+}
+
+CF_INLINE CFBasicHashValue *__CFBasicHashGetKeys(CFConstBasicHashRef ht) {
+ return (CFBasicHashValue *)ht->pointers[ht->bits.keys_offset];
+}
+
+CF_INLINE void __CFBasicHashSetKeys(CFBasicHashRef ht, CFBasicHashValue *ptr) {
+ __AssignWithWriteBarrier(&ht->pointers[ht->bits.keys_offset], ptr);
+}
+
+CF_INLINE void *__CFBasicHashGetCounts(CFConstBasicHashRef ht) {
+ return (void *)ht->pointers[ht->bits.counts_offset];
+}
+
+CF_INLINE void __CFBasicHashSetCounts(CFBasicHashRef ht, void *ptr) {
+ __AssignWithWriteBarrier(&ht->pointers[ht->bits.counts_offset], ptr);
+}
+
+CF_INLINE uintptr_t __CFBasicHashGetValue(CFConstBasicHashRef ht, CFIndex idx) {
+ uintptr_t val = __CFBasicHashGetValues(ht)[idx].neutral;
+ if (__CFBasicHashSubABZero == val) return 0UL;
+ if (__CFBasicHashSubABOne == val) return ~0UL;
+ return val;
+}
+
+CF_INLINE void __CFBasicHashSetValue(CFBasicHashRef ht, CFIndex idx, uintptr_t stack_value, Boolean ignoreOld, Boolean literal) {
+ CFBasicHashValue *valuep = &(__CFBasicHashGetValues(ht)[idx]);
+ uintptr_t old_value = ignoreOld ? 0 : valuep->neutral;
+ if (!literal) {
+ if (0UL == stack_value) stack_value = __CFBasicHashSubABZero;
+ if (~0UL == stack_value) stack_value = __CFBasicHashSubABOne;
+ }
+ if (CFBasicHashHasStrongValues(ht)) valuep->strong = (id)stack_value; else valuep->neutral = stack_value;
+ if (!ignoreOld) {
+ if (!(old_value == 0UL || old_value == ~0UL)) {
+ if (__CFBasicHashSubABZero == old_value) old_value = 0UL;
+ if (__CFBasicHashSubABOne == old_value) old_value = ~0UL;
+ __CFBasicHashEjectValue(ht, old_value);
+ }
+ }
+}
+
+CF_INLINE uintptr_t __CFBasicHashGetKey(CFConstBasicHashRef ht, CFIndex idx) {
+ if (ht->bits.keys_offset) {
+ uintptr_t key = __CFBasicHashGetKeys(ht)[idx].neutral;
+ if (__CFBasicHashSubABZero == key) return 0UL;
+ if (__CFBasicHashSubABOne == key) return ~0UL;
+ return key;
+ }
+ if (ht->bits.indirect_keys) {
+ uintptr_t stack_value = __CFBasicHashGetValue(ht, idx);
+ return ht->callbacks->getIndirectKey(ht, stack_value);
+ }
+ return __CFBasicHashGetValue(ht, idx);
+}
+
+CF_INLINE void __CFBasicHashSetKey(CFBasicHashRef ht, CFIndex idx, uintptr_t stack_key, Boolean ignoreOld, Boolean literal) {
+ if (0 == ht->bits.keys_offset) HALT;
+ CFBasicHashValue *keyp = &(__CFBasicHashGetKeys(ht)[idx]);
+ uintptr_t old_key = ignoreOld ? 0 : keyp->neutral;
+ if (!literal) {
+ if (0UL == stack_key) stack_key = __CFBasicHashSubABZero;
+ if (~0UL == stack_key) stack_key = __CFBasicHashSubABOne;
+ }
+ if (CFBasicHashHasStrongKeys(ht)) keyp->strong = (id)stack_key; else keyp->neutral = stack_key;
+ if (!ignoreOld) {
+ if (!(old_key == 0UL || old_key == ~0UL)) {
+ if (__CFBasicHashSubABZero == old_key) old_key = 0UL;
+ if (__CFBasicHashSubABOne == old_key) old_key = ~0UL;
+ __CFBasicHashEjectKey(ht, old_key);
+ }
+ }
+}
+
+CF_INLINE uintptr_t __CFBasicHashIsEmptyOrDeleted(CFConstBasicHashRef ht, CFIndex idx) {
+ uintptr_t stack_value = __CFBasicHashGetValues(ht)[idx].neutral;
+ return (0UL == stack_value || ~0UL == stack_value);
+}
+
+CF_INLINE uintptr_t __CFBasicHashIsDeleted(CFConstBasicHashRef ht, CFIndex idx) {
+ uintptr_t stack_value = __CFBasicHashGetValues(ht)[idx].neutral;
+ return (~0UL == stack_value);
+}
+
+CF_INLINE uintptr_t __CFBasicHashGetSlotCount(CFConstBasicHashRef ht, CFIndex idx) {
+ void *counts = __CFBasicHashGetCounts(ht);
+ switch (ht->bits.counts_width) {
+ case 0: return ((uint8_t *)counts)[idx];
+ case 1: return ((uint16_t *)counts)[idx];
+ case 2: return ((uint32_t *)counts)[idx];
+ case 3: return ((uint64_t *)counts)[idx];
+ }
+ return 0;
+}
+
+CF_INLINE void __CFBasicHashBumpCounts(CFBasicHashRef ht) {
+ void *counts = __CFBasicHashGetCounts(ht);
+ CFAllocatorRef allocator = CFGetAllocator(ht);
+ switch (ht->bits.counts_width) {
+ case 0: {
+ uint8_t *counts08 = (uint8_t *)counts;
+ ht->bits.counts_width = 1;
+ CFIndex num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+ uint16_t *counts16 = (uint16_t *)__CFBasicHashAllocateMemory(ht, num_buckets, 2, false, false);
+ if (!counts16) HALT;
+ __SetLastAllocationEventName(counts16, "CFBasicHash (count-store)");
+ for (CFIndex idx2 = 0; idx2 < num_buckets; idx2++) {
+ counts16[idx2] = counts08[idx2];
+ }
+ __CFBasicHashSetCounts(ht, counts16);
+ if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+ CFAllocatorDeallocate(allocator, counts08);
+ }
+ break;
+ }
+ case 1: {
+ uint16_t *counts16 = (uint16_t *)counts;
+ ht->bits.counts_width = 2;
+ CFIndex num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+ uint32_t *counts32 = (uint32_t *)__CFBasicHashAllocateMemory(ht, num_buckets, 4, false, false);
+ if (!counts32) HALT;
+ __SetLastAllocationEventName(counts32, "CFBasicHash (count-store)");
+ for (CFIndex idx2 = 0; idx2 < num_buckets; idx2++) {
+ counts32[idx2] = counts16[idx2];
+ }
+ __CFBasicHashSetCounts(ht, counts32);
+ if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+ CFAllocatorDeallocate(allocator, counts16);
+ }
+ break;
+ }
+ case 2: {
+ uint32_t *counts32 = (uint32_t *)counts;
+ ht->bits.counts_width = 3;
+ CFIndex num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+ uint64_t *counts64 = (uint64_t *)__CFBasicHashAllocateMemory(ht, num_buckets, 8, false, false);
+ if (!counts64) HALT;
+ __SetLastAllocationEventName(counts64, "CFBasicHash (count-store)");
+ for (CFIndex idx2 = 0; idx2 < num_buckets; idx2++) {
+ counts64[idx2] = counts32[idx2];
+ }
+ __CFBasicHashSetCounts(ht, counts64);
+ if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+ CFAllocatorDeallocate(allocator, counts32);
+ }
+ break;
+ }
+ case 3: {
+ HALT;
+ break;
+ }
+ }
+}
+
+static void __CFBasicHashIncSlotCount(CFBasicHashRef ht, CFIndex idx) {
+ void *counts = __CFBasicHashGetCounts(ht);
+ switch (ht->bits.counts_width) {
+ case 0: {
+ uint8_t *counts08 = (uint8_t *)counts;
+ uint8_t val = counts08[idx];
+ if (val < INT8_MAX) {
+ counts08[idx] = val + 1;
+ return;
+ }
+ __CFBasicHashBumpCounts(ht);
+ __CFBasicHashIncSlotCount(ht, idx);
+ break;
+ }
+ case 1: {
+ uint16_t *counts16 = (uint16_t *)counts;
+ uint16_t val = counts16[idx];
+ if (val < INT16_MAX) {
+ counts16[idx] = val + 1;
+ return;
+ }
+ __CFBasicHashBumpCounts(ht);
+ __CFBasicHashIncSlotCount(ht, idx);
+ break;
+ }
+ case 2: {
+ uint32_t *counts32 = (uint32_t *)counts;
+ uint32_t val = counts32[idx];
+ if (val < INT32_MAX) {
+ counts32[idx] = val + 1;
+ return;
+ }
+ __CFBasicHashBumpCounts(ht);
+ __CFBasicHashIncSlotCount(ht, idx);
+ break;
+ }
+ case 3: {
+ uint64_t *counts64 = (uint64_t *)counts;
+ uint64_t val = counts64[idx];
+ if (val < INT64_MAX) {
+ counts64[idx] = val + 1;
+ return;
+ }
+ __CFBasicHashBumpCounts(ht);
+ __CFBasicHashIncSlotCount(ht, idx);
+ break;
+ }
+ }
+}
+
+CF_INLINE void __CFBasicHashDecSlotCount(CFBasicHashRef ht, CFIndex idx) {
+ void *counts = __CFBasicHashGetCounts(ht);
+ switch (ht->bits.counts_width) {
+ case 0: ((uint8_t *)counts)[idx]--; return;
+ case 1: ((uint16_t *)counts)[idx]--; return;
+ case 2: ((uint32_t *)counts)[idx]--; return;
+ case 3: ((uint64_t *)counts)[idx]--; return;
+ }
+}
+
+CF_INLINE uintptr_t *__CFBasicHashGetHashes(CFConstBasicHashRef ht) {
+ return (uintptr_t *)ht->pointers[ht->bits.hashes_offset];
+}
+
+CF_INLINE void __CFBasicHashSetHashes(CFBasicHashRef ht, uintptr_t *ptr) {
+ __AssignWithWriteBarrier(&ht->pointers[ht->bits.hashes_offset], ptr);
+}
+
+
+// to expose the load factor, expose this function to customization
+CF_INLINE CFIndex __CFBasicHashGetCapacityForNumBuckets(CFConstBasicHashRef ht, CFIndex num_buckets_idx) {
+ return __CFBasicHashTableCapacities[num_buckets_idx];
+}
+
+CF_INLINE CFIndex __CFBasicHashGetNumBucketsIndexForCapacity(CFConstBasicHashRef ht, CFIndex capacity) {
+ for (CFIndex idx = 0; idx < 64; idx++) {
+ if (capacity <= __CFBasicHashGetCapacityForNumBuckets(ht, idx)) return idx;
+ }
+ HALT;
+ return 0;
+}
+
+__private_extern__ CFIndex CFBasicHashGetNumBuckets(CFConstBasicHashRef ht) {
+ return __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+}
+
+__private_extern__ CFIndex CFBasicHashGetCapacity(CFConstBasicHashRef ht) {
+ return __CFBasicHashGetCapacityForNumBuckets(ht, ht->bits.num_buckets_idx);
+}
+
+// In returned struct, .count is zero if the bucket is empty or deleted,
+// and the .weak_key field indicates which. .idx is either the index of
+// 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) {
+ CFBasicHashBucket result;
+ result.idx = idx;
+ if (__CFBasicHashIsEmptyOrDeleted(ht, idx)) {
+ result.count = 0;
+ result.weak_value = 0;
+ result.weak_key = 0;
+ } else {
+ result.count = (ht->bits.counts_offset) ? __CFBasicHashGetSlotCount(ht, idx) : 1;
+ result.weak_value = __CFBasicHashGetValue(ht, idx);
+ result.weak_key = __CFBasicHashGetKey(ht, idx);
+ }
+ return result;
+}
+
+#if defined(__arm__)
+static uintptr_t __CFBasicHashFold(uintptr_t dividend, uint8_t idx) {
+ switch (idx) {
+ case 1: return dividend % 3;
+ case 2: return dividend % 7;
+ case 3: return dividend % 13;
+ case 4: return dividend % 23;
+ case 5: return dividend % 41;
+ case 6: return dividend % 71;
+ case 7: return dividend % 127;
+ case 8: return dividend % 191;
+ case 9: return dividend % 251;
+ case 10: return dividend % 383;
+ case 11: return dividend % 631;
+ case 12: return dividend % 1087;
+ case 13: return dividend % 1723;
+ case 14: return dividend % 2803;
+ case 15: return dividend % 4523;
+ case 16: return dividend % 7351;
+ case 17: return dividend % 11959;
+ case 18: return dividend % 19447;
+ case 19: return dividend % 31231;
+ case 20: return dividend % 50683;
+ case 21: return dividend % 81919;
+ case 22: return dividend % 132607;
+ case 23: return dividend % 214519;
+ case 24: return dividend % 346607;
+ case 25: return dividend % 561109;
+ case 26: return dividend % 907759;
+ case 27: return dividend % 1468927;
+ case 28: return dividend % 2376191;
+ case 29: return dividend % 3845119;
+ case 30: return dividend % 6221311;
+ case 31: return dividend % 10066421;
+ case 32: return dividend % 16287743;
+ case 33: return dividend % 26354171;
+ case 34: return dividend % 42641881;
+ case 35: return dividend % 68996069;
+ case 36: return dividend % 111638519;
+ case 37: return dividend % 180634607;
+ case 38: return dividend % 292272623;
+ case 39: return dividend % 472907251;
+ }
+ HALT;
+ return ~0;
+}
+#endif
+
+
+#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Linear
+#define FIND_BUCKET_HASH_STYLE 1
+#define FIND_BUCKET_FOR_REHASH 0
+#define FIND_BUCKET_FOR_INDIRECT_KEY 0
+#include "CFBasicHashFindBucket.m"
+
+#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Linear_NoCollision
+#define FIND_BUCKET_HASH_STYLE 1
+#define FIND_BUCKET_FOR_REHASH 1
+#define FIND_BUCKET_FOR_INDIRECT_KEY 0
+#include "CFBasicHashFindBucket.m"
+
+#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Linear_Indirect
+#define FIND_BUCKET_HASH_STYLE 1
+#define FIND_BUCKET_FOR_REHASH 0
+#define FIND_BUCKET_FOR_INDIRECT_KEY 1
+#include "CFBasicHashFindBucket.m"
+
+#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Linear_Indirect_NoCollision
+#define FIND_BUCKET_HASH_STYLE 1
+#define FIND_BUCKET_FOR_REHASH 1
+#define FIND_BUCKET_FOR_INDIRECT_KEY 1
+#include "CFBasicHashFindBucket.m"
+
+#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Double
+#define FIND_BUCKET_HASH_STYLE 2
+#define FIND_BUCKET_FOR_REHASH 0
+#define FIND_BUCKET_FOR_INDIRECT_KEY 0
+#include "CFBasicHashFindBucket.m"
+
+#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Double_NoCollision
+#define FIND_BUCKET_HASH_STYLE 2
+#define FIND_BUCKET_FOR_REHASH 1
+#define FIND_BUCKET_FOR_INDIRECT_KEY 0
+#include "CFBasicHashFindBucket.m"
+
+#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Double_Indirect
+#define FIND_BUCKET_HASH_STYLE 2
+#define FIND_BUCKET_FOR_REHASH 0
+#define FIND_BUCKET_FOR_INDIRECT_KEY 1
+#include "CFBasicHashFindBucket.m"
+
+#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Double_Indirect_NoCollision
+#define FIND_BUCKET_HASH_STYLE 2
+#define FIND_BUCKET_FOR_REHASH 1
+#define FIND_BUCKET_FOR_INDIRECT_KEY 1
+#include "CFBasicHashFindBucket.m"
+
+#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Exponential
+#define FIND_BUCKET_HASH_STYLE 3
+#define FIND_BUCKET_FOR_REHASH 0
+#define FIND_BUCKET_FOR_INDIRECT_KEY 0
+#include "CFBasicHashFindBucket.m"
+
+#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Exponential_NoCollision
+#define FIND_BUCKET_HASH_STYLE 3
+#define FIND_BUCKET_FOR_REHASH 1
+#define FIND_BUCKET_FOR_INDIRECT_KEY 0
+#include "CFBasicHashFindBucket.m"
+
+#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Exponential_Indirect
+#define FIND_BUCKET_HASH_STYLE 3
+#define FIND_BUCKET_FOR_REHASH 0
+#define FIND_BUCKET_FOR_INDIRECT_KEY 1
+#include "CFBasicHashFindBucket.m"
+
+#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Exponential_Indirect_NoCollision
+#define FIND_BUCKET_HASH_STYLE 3
+#define FIND_BUCKET_FOR_REHASH 1
+#define FIND_BUCKET_FOR_INDIRECT_KEY 1
+#include "CFBasicHashFindBucket.m"
+
+
+CF_INLINE CFBasicHashBucket __CFBasicHashFindBucket(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ if (0 == ht->bits.num_buckets_idx) {
+ CFBasicHashBucket result = {kCFNotFound, 0UL, 0UL, 0};
+ return result;
+ }
+ if (ht->bits.indirect_keys) {
+ switch (ht->bits.hash_style) {
+ case __kCFBasicHashLinearHashingValue: return ___CFBasicHashFindBucket_Linear_Indirect(ht, stack_key);
+ case __kCFBasicHashDoubleHashingValue: return ___CFBasicHashFindBucket_Double_Indirect(ht, stack_key);
+ case __kCFBasicHashExponentialHashingValue: return ___CFBasicHashFindBucket_Exponential_Indirect(ht, stack_key);
+ }
+ } else {
+ switch (ht->bits.hash_style) {
+ case __kCFBasicHashLinearHashingValue: return ___CFBasicHashFindBucket_Linear(ht, stack_key);
+ case __kCFBasicHashDoubleHashingValue: return ___CFBasicHashFindBucket_Double(ht, stack_key);
+ case __kCFBasicHashExponentialHashingValue: return ___CFBasicHashFindBucket_Exponential(ht, stack_key);
+ }
+ }
+ HALT;
+ CFBasicHashBucket result = {kCFNotFound, 0UL, 0UL, 0};
+ return result;
+}
+
+CF_INLINE CFIndex __CFBasicHashFindBucket_NoCollision(CFConstBasicHashRef ht, uintptr_t stack_key, uintptr_t key_hash) {
+ if (0 == ht->bits.num_buckets_idx) {
+ return kCFNotFound;
+ }
+ if (ht->bits.indirect_keys) {
+ switch (ht->bits.hash_style) {
+ case __kCFBasicHashLinearHashingValue: return ___CFBasicHashFindBucket_Linear_Indirect_NoCollision(ht, stack_key, key_hash);
+ case __kCFBasicHashDoubleHashingValue: return ___CFBasicHashFindBucket_Double_Indirect_NoCollision(ht, stack_key, key_hash);
+ case __kCFBasicHashExponentialHashingValue: return ___CFBasicHashFindBucket_Exponential_Indirect_NoCollision(ht, stack_key, key_hash);
+ }
+ } else {
+ switch (ht->bits.hash_style) {
+ case __kCFBasicHashLinearHashingValue: return ___CFBasicHashFindBucket_Linear_NoCollision(ht, stack_key, key_hash);
+ case __kCFBasicHashDoubleHashingValue: return ___CFBasicHashFindBucket_Double_NoCollision(ht, stack_key, key_hash);
+ case __kCFBasicHashExponentialHashingValue: return ___CFBasicHashFindBucket_Exponential_NoCollision(ht, stack_key, key_hash);
+ }
+ }
+ HALT;
+ return kCFNotFound;
+}
+
+__private_extern__ CFBasicHashBucket CFBasicHashFindBucket(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ if (__CFBasicHashSubABZero == stack_key || __CFBasicHashSubABOne == stack_key) {
+ CFBasicHashBucket result = {kCFNotFound, 0UL, 0UL, 0};
+ return result;
+ }
+ return __CFBasicHashFindBucket(ht, stack_key);
+}
+
+__private_extern__ uint16_t CFBasicHashGetSpecialBits(CFConstBasicHashRef ht) {
+ return ht->bits.special_bits;
+}
+
+__private_extern__ uint16_t CFBasicHashSetSpecialBits(CFBasicHashRef ht, uint16_t bits) {
+ uint16_t old = ht->bits.special_bits;
+ ht->bits.special_bits = bits;
+ return old;
+}
+
+__private_extern__ 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;
+ if (__CFBasicHashHasHashCache(ht)) flags |= kCFBasicHashHasHashCache;
+ return flags;
+}
+
+__private_extern__ const CFBasicHashCallbacks *CFBasicHashGetCallbacks(CFConstBasicHashRef ht) {
+ return ht->callbacks;
+}
+
+__private_extern__ CFIndex CFBasicHashGetCount(CFConstBasicHashRef ht) {
+ if (ht->bits.counts_offset) {
+ CFIndex total = 0L;
+ CFIndex cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+ for (CFIndex idx = 0; idx < cnt; idx++) {
+ total += __CFBasicHashGetSlotCount(ht, idx);
+ }
+ return total;
+ }
+ return (CFIndex)ht->bits.used_buckets;
+}
+
+__private_extern__ CFIndex CFBasicHashGetCountOfKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ if (__CFBasicHashSubABZero == stack_key || __CFBasicHashSubABOne == stack_key) {
+ return 0L;
+ }
+ if (0L == ht->bits.used_buckets) {
+ return 0L;
+ }
+ return __CFBasicHashFindBucket(ht, stack_key).count;
+}
+
+__private_extern__ CFIndex CFBasicHashGetCountOfValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
+ if (__CFBasicHashSubABZero == stack_value) {
+ return 0L;
+ }
+ if (0L == ht->bits.used_buckets) {
+ return 0L;
+ }
+ if (!(ht->bits.keys_offset)) {
+ return __CFBasicHashFindBucket(ht, stack_value).count;
+ }
+ __block CFIndex total = 0L;
+ CFBasicHashApply(ht, ^(CFBasicHashBucket bkt) {
+ if ((stack_value == bkt.weak_value) || __CFBasicHashTestEqualValue(ht, bkt.weak_value, stack_value)) total += bkt.count;
+ return (Boolean)true;
+ });
+ return total;
+}
+
+__private_extern__ Boolean CFBasicHashesAreEqual(CFConstBasicHashRef ht1, CFConstBasicHashRef ht2) {
+ CFIndex cnt1 = CFBasicHashGetCount(ht1);
+ if (cnt1 != CFBasicHashGetCount(ht2)) return false;
+ if (0 == cnt1) return true;
+ __block Boolean equal = true;
+ CFBasicHashApply(ht1, ^(CFBasicHashBucket bkt1) {
+ CFBasicHashBucket bkt2 = __CFBasicHashFindBucket(ht2, bkt1.weak_key);
+ if (bkt1.count != bkt2.count) {
+ equal = false;
+ return (Boolean)false;
+ }
+ if ((ht1->bits.keys_offset) && (bkt1.weak_value != bkt2.weak_value) && !__CFBasicHashTestEqualValue(ht1, bkt1.weak_value, bkt2.weak_value)) {
+ equal = false;
+ return (Boolean)false;
+ }
+ return (Boolean)true;
+ });
+ return equal;
+}
+
+__private_extern__ 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);
+ if (0 < bkt.count) {
+ if (!block(bkt)) {
+ return;
+ }
+ used--;
+ }
+ }
+}
+
+__private_extern__ 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];
+ if (cnt < range.location + range.length) HALT;
+ for (CFIndex idx = 0; idx < range.length; idx++) {
+ CFBasicHashBucket bkt = CFBasicHashGetBucket(ht, range.location + idx);
+ if (0 < bkt.count) {
+ if (!block(bkt)) {
+ return;
+ }
+ }
+ }
+}
+
+__private_extern__ 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++) {
+ CFBasicHashBucket bkt = CFBasicHashGetBucket(ht, idx);
+ if (0 < bkt.count) {
+ used--;
+ for (CFIndex cnt = bkt.count; cnt-- && offset < bufferslen;) {
+ if (weak_values) { weak_values[offset] = bkt.weak_value; }
+ if (weak_keys) { weak_keys[offset] = bkt.weak_key; }
+ offset++;
+ }
+ }
+ }
+}
+
+__private_extern__ 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->itemsPtr = (unsigned long *)stackbuffer;
+ CFIndex cntx = 0;
+ CFIndex used = (CFIndex)ht->bits.used_buckets, cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+ for (CFIndex idx = (CFIndex)state->state; 0 < used && idx < cnt && cntx < (CFIndex)count; idx++) {
+ CFBasicHashBucket bkt = CFBasicHashGetBucket(ht, idx);
+ if (0 < bkt.count) {
+ state->itemsPtr[cntx++] = (unsigned long)bkt.weak_key;
+ used--;
+ }
+ state->state++;
+ }
+ return cntx;
+}
+
+#if ENABLE_MEMORY_COUNTERS
+static volatile int64_t __CFBasicHashTotalCount = 0ULL;
+static volatile int64_t __CFBasicHashTotalSize = 0ULL;
+static volatile int64_t __CFBasicHashPeakCount = 0ULL;
+static volatile int64_t __CFBasicHashPeakSize = 0ULL;
+static volatile int32_t __CFBasicHashSizes[64] = {0};
+#endif
+
+static void __CFBasicHashDrain(CFBasicHashRef ht, Boolean forFinalization) {
+#if ENABLE_MEMORY_COUNTERS
+ OSAtomicAdd64Barrier(-1 * (int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
+#endif
+
+ CFIndex old_num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+
+ CFAllocatorRef allocator = CFGetAllocator(ht);
+ Boolean nullify = (!forFinalization || !CF_IS_COLLECTABLE_ALLOCATOR(allocator));
+
+ CFBasicHashValue *old_values = NULL, *old_keys = NULL;
+ void *old_counts = NULL;
+ uintptr_t *old_hashes = NULL;
+
+ old_values = __CFBasicHashGetValues(ht);
+ if (nullify) __CFBasicHashSetValues(ht, NULL);
+ if (ht->bits.keys_offset) {
+ old_keys = __CFBasicHashGetKeys(ht);
+ if (nullify) __CFBasicHashSetKeys(ht, NULL);
+ }
+ if (ht->bits.counts_offset) {
+ old_counts = __CFBasicHashGetCounts(ht);
+ if (nullify) __CFBasicHashSetCounts(ht, NULL);
+ }
+ if (__CFBasicHashHasHashCache(ht)) {
+ old_hashes = __CFBasicHashGetHashes(ht);
+ if (nullify) __CFBasicHashSetHashes(ht, NULL);
+ }
+
+ if (nullify) {
+ ht->bits.mutations++;
+ ht->bits.num_buckets_idx = 0;
+ ht->bits.used_buckets = 0;
+ ht->bits.deleted = 0;
+ }
+
+ for (CFIndex idx = 0; idx < old_num_buckets; idx++) {
+ uintptr_t stack_value = old_values[idx].neutral;
+ if (stack_value != 0UL && stack_value != ~0UL) {
+ uintptr_t old_value = stack_value;
+ if (__CFBasicHashSubABZero == old_value) old_value = 0UL;
+ if (__CFBasicHashSubABOne == old_value) old_value = ~0UL;
+ __CFBasicHashEjectValue(ht, old_value);
+ if (old_keys) {
+ uintptr_t old_key = old_keys[idx].neutral;
+ if (__CFBasicHashSubABZero == old_key) old_key = 0UL;
+ if (__CFBasicHashSubABOne == old_key) old_key = ~0UL;
+ __CFBasicHashEjectKey(ht, old_key);
+ }
+ }
+ }
+
+ if (forFinalization) {
+ ht->callbacks->freeCallbacks(ht, allocator, ht->callbacks);
+ }
+
+ if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+ CFAllocatorDeallocate(allocator, old_values);
+ CFAllocatorDeallocate(allocator, old_keys);
+ CFAllocatorDeallocate(allocator, old_counts);
+ CFAllocatorDeallocate(allocator, old_hashes);
+ }
+
+#if ENABLE_MEMORY_COUNTERS
+ int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
+ while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
+#endif
+}
+
+static void __CFBasicHashRehash(CFBasicHashRef ht, CFIndex newItemCount) {
+#if ENABLE_MEMORY_COUNTERS
+ OSAtomicAdd64Barrier(-1 * (int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
+ OSAtomicAdd32Barrier(-1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
+#endif
+
+ if (COCOA_HASHTABLE_REHASH_START_ENABLED()) COCOA_HASHTABLE_REHASH_START(ht, CFBasicHashGetNumBuckets(ht), CFBasicHashGetSize(ht, true));
+
+ CFIndex new_num_buckets_idx = ht->bits.num_buckets_idx;
+ if (0 != newItemCount) {
+ if (newItemCount < 0) newItemCount = 0;
+ CFIndex new_capacity_req = ht->bits.used_buckets + newItemCount;
+ new_num_buckets_idx = __CFBasicHashGetNumBucketsIndexForCapacity(ht, new_capacity_req);
+ if (1 == newItemCount && ht->bits.fast_grow) {
+ new_num_buckets_idx++;
+ }
+ }
+
+ CFIndex new_num_buckets = __CFBasicHashTableSizes[new_num_buckets_idx];
+ CFIndex old_num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+
+ CFBasicHashValue *new_values = NULL, *new_keys = NULL;
+ void *new_counts = NULL;
+ uintptr_t *new_hashes = NULL;
+
+ if (0 < new_num_buckets) {
+ new_values = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), CFBasicHashHasStrongValues(ht), __CFBasicHashHasCompactableValues(ht));
+ 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));
+ if (!new_keys) HALT;
+ __SetLastAllocationEventName(new_keys, "CFBasicHash (key-store)");
+ memset(new_keys, 0, new_num_buckets * sizeof(CFBasicHashValue));
+ }
+ if (ht->bits.counts_offset) {
+ new_counts = (uintptr_t *)__CFBasicHashAllocateMemory(ht, new_num_buckets, (1 << ht->bits.counts_width), false, false);
+ if (!new_counts) HALT;
+ __SetLastAllocationEventName(new_counts, "CFBasicHash (count-store)");
+ memset(new_counts, 0, new_num_buckets * (1 << ht->bits.counts_width));
+ }
+ if (__CFBasicHashHasHashCache(ht)) {
+ new_hashes = (uintptr_t *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(uintptr_t), false, false);
+ if (!new_hashes) HALT;
+ __SetLastAllocationEventName(new_hashes, "CFBasicHash (hash-store)");
+ memset(new_hashes, 0, new_num_buckets * sizeof(uintptr_t));
+ }
+ }
+
+ ht->bits.num_buckets_idx = new_num_buckets_idx;
+ ht->bits.deleted = 0;
+
+ CFBasicHashValue *old_values = NULL, *old_keys = NULL;
+ void *old_counts = NULL;
+ uintptr_t *old_hashes = NULL;
+
+ old_values = __CFBasicHashGetValues(ht);
+ __CFBasicHashSetValues(ht, new_values);
+ if (ht->bits.keys_offset) {
+ old_keys = __CFBasicHashGetKeys(ht);
+ __CFBasicHashSetKeys(ht, new_keys);
+ }
+ if (ht->bits.counts_offset) {
+ old_counts = __CFBasicHashGetCounts(ht);
+ __CFBasicHashSetCounts(ht, new_counts);
+ }
+ if (__CFBasicHashHasHashCache(ht)) {
+ old_hashes = __CFBasicHashGetHashes(ht);
+ __CFBasicHashSetHashes(ht, new_hashes);
+ }
+
+ if (0 < old_num_buckets) {
+ for (CFIndex idx = 0; idx < old_num_buckets; idx++) {
+ uintptr_t stack_value = old_values[idx].neutral;
+ if (stack_value != 0UL && stack_value != ~0UL) {
+ if (__CFBasicHashSubABZero == stack_value) stack_value = 0UL;
+ if (__CFBasicHashSubABOne == stack_value) stack_value = ~0UL;
+ uintptr_t stack_key = stack_value;
+ if (ht->bits.keys_offset) {
+ stack_key = old_keys[idx].neutral;
+ if (__CFBasicHashSubABZero == stack_key) stack_key = 0UL;
+ if (__CFBasicHashSubABOne == stack_key) stack_key = ~0UL;
+ }
+ if (ht->bits.indirect_keys) {
+ stack_key = ht->callbacks->getIndirectKey(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);
+ if (old_keys) {
+ __CFBasicHashSetKey(ht, bkt_idx, stack_key, false, false);
+ }
+ if (old_counts) {
+ switch (ht->bits.counts_width) {
+ case 0: ((uint8_t *)new_counts)[bkt_idx] = ((uint8_t *)old_counts)[idx]; break;
+ case 1: ((uint16_t *)new_counts)[bkt_idx] = ((uint16_t *)old_counts)[idx]; break;
+ case 2: ((uint32_t *)new_counts)[bkt_idx] = ((uint32_t *)old_counts)[idx]; break;
+ case 3: ((uint64_t *)new_counts)[bkt_idx] = ((uint64_t *)old_counts)[idx]; break;
+ }
+ }
+ if (old_hashes) {
+ new_hashes[bkt_idx] = old_hashes[idx];
+ }
+ }
+ }
+ }
+
+ CFAllocatorRef allocator = CFGetAllocator(ht);
+ if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+ CFAllocatorDeallocate(allocator, old_values);
+ CFAllocatorDeallocate(allocator, old_keys);
+ CFAllocatorDeallocate(allocator, old_counts);
+ CFAllocatorDeallocate(allocator, old_hashes);
+ }
+
+ if (COCOA_HASHTABLE_REHASH_END_ENABLED()) COCOA_HASHTABLE_REHASH_END(ht, CFBasicHashGetNumBuckets(ht), CFBasicHashGetSize(ht, true));
+
+#if ENABLE_MEMORY_COUNTERS
+ int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), &__CFBasicHashTotalSize);
+ while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
+ OSAtomicAdd32Barrier(1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
+#endif
+}
+
+__private_extern__ void CFBasicHashSetCapacity(CFBasicHashRef ht, CFIndex capacity) {
+ if (!CFBasicHashIsMutable(ht)) HALT;
+ if (ht->bits.used_buckets < capacity) {
+ ht->bits.mutations++;
+ __CFBasicHashRehash(ht, capacity - ht->bits.used_buckets);
+ }
+}
+
+static void __CFBasicHashAddValue(CFBasicHashRef ht, CFIndex bkt_idx, uintptr_t stack_key, uintptr_t stack_value) {
+ ht->bits.mutations++;
+ if (CFBasicHashGetCapacity(ht) < ht->bits.used_buckets + 1) {
+ __CFBasicHashRehash(ht, 1);
+ bkt_idx = __CFBasicHashFindBucket_NoCollision(ht, stack_key, 0);
+ } else if (__CFBasicHashIsDeleted(ht, bkt_idx)) {
+ ht->bits.deleted--;
+ }
+ uintptr_t key_hash = 0;
+ if (__CFBasicHashHasHashCache(ht)) {
+ key_hash = __CFBasicHashHashKey(ht, stack_key);
+ }
+ stack_value = __CFBasicHashImportValue(ht, stack_value);
+ if (ht->bits.keys_offset) {
+ stack_key = __CFBasicHashImportKey(ht, stack_key);
+ }
+ __CFBasicHashSetValue(ht, bkt_idx, stack_value, false, false);
+ if (ht->bits.keys_offset) {
+ __CFBasicHashSetKey(ht, bkt_idx, stack_key, false, false);
+ }
+ if (ht->bits.counts_offset) {
+ __CFBasicHashIncSlotCount(ht, bkt_idx);
+ }
+ if (__CFBasicHashHasHashCache(ht)) {
+ __CFBasicHashGetHashes(ht)[bkt_idx] = key_hash;
+ }
+ ht->bits.used_buckets++;
+}
+
+static void __CFBasicHashReplaceValue(CFBasicHashRef ht, CFIndex bkt_idx, uintptr_t stack_key, uintptr_t stack_value) {
+ ht->bits.mutations++;
+ stack_value = __CFBasicHashImportValue(ht, stack_value);
+ if (ht->bits.keys_offset) {
+ stack_key = __CFBasicHashImportKey(ht, stack_key);
+ }
+ __CFBasicHashSetValue(ht, bkt_idx, stack_value, false, false);
+ if (ht->bits.keys_offset) {
+ __CFBasicHashSetKey(ht, bkt_idx, stack_key, false, false);
+ }
+}
+
+static void __CFBasicHashRemoveValue(CFBasicHashRef ht, CFIndex bkt_idx) {
+ ht->bits.mutations++;
+ __CFBasicHashSetValue(ht, bkt_idx, ~0UL, false, true);
+ if (ht->bits.keys_offset) {
+ __CFBasicHashSetKey(ht, bkt_idx, ~0UL, false, true);
+ }
+ if (ht->bits.counts_offset) {
+ __CFBasicHashDecSlotCount(ht, bkt_idx);
+ }
+ if (__CFBasicHashHasHashCache(ht)) {
+ __CFBasicHashGetHashes(ht)[bkt_idx] = 0;
+ }
+ ht->bits.used_buckets--;
+ ht->bits.deleted++;
+ Boolean do_shrink = false;
+ if (ht->bits.fast_grow) { // == slow shrink
+ do_shrink = (5 < ht->bits.num_buckets_idx && ht->bits.used_buckets < __CFBasicHashGetCapacityForNumBuckets(ht, ht->bits.num_buckets_idx - 5));
+ } else {
+ do_shrink = (2 < ht->bits.num_buckets_idx && ht->bits.used_buckets < __CFBasicHashGetCapacityForNumBuckets(ht, ht->bits.num_buckets_idx - 2));
+ }
+ if (do_shrink) {
+ __CFBasicHashRehash(ht, -1);
+ return;
+ }
+ do_shrink = (0 == ht->bits.deleted); // .deleted roll-over
+ CFIndex num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+ do_shrink = do_shrink || ((20 <= num_buckets) && (num_buckets / 4 <= ht->bits.deleted));
+ if (do_shrink) {
+ __CFBasicHashRehash(ht, 0);
+ }
+}
+
+__private_extern__ 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;
+ if (__CFBasicHashSubABZero == stack_value) HALT;
+ if (__CFBasicHashSubABOne == stack_value) HALT;
+ CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key);
+ if (0 < bkt.count) {
+ ht->bits.mutations++;
+ if (ht->bits.counts_offset && bkt.count < LONG_MAX) { // if not yet as large as a CFIndex can be... otherwise clamp and do nothing
+ __CFBasicHashIncSlotCount(ht, bkt.idx);
+ return true;
+ }
+ } else {
+ __CFBasicHashAddValue(ht, bkt.idx, stack_key, stack_value);
+ return true;
+ }
+ return false;
+}
+
+__private_extern__ 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;
+ if (__CFBasicHashSubABZero == stack_value) HALT;
+ if (__CFBasicHashSubABOne == stack_value) HALT;
+ CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key);
+ if (0 < bkt.count) {
+ __CFBasicHashReplaceValue(ht, bkt.idx, stack_key, stack_value);
+ }
+}
+
+__private_extern__ 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;
+ if (__CFBasicHashSubABZero == stack_value) HALT;
+ if (__CFBasicHashSubABOne == stack_value) HALT;
+ CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key);
+ if (0 < bkt.count) {
+ __CFBasicHashReplaceValue(ht, bkt.idx, stack_key, stack_value);
+ } else {
+ __CFBasicHashAddValue(ht, bkt.idx, stack_key, stack_value);
+ }
+}
+
+__private_extern__ 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);
+ if (1 < bkt.count) {
+ ht->bits.mutations++;
+ if (ht->bits.counts_offset && bkt.count < LONG_MAX) { // if not as large as a CFIndex can be... otherwise clamp and do nothing
+ __CFBasicHashDecSlotCount(ht, bkt.idx);
+ }
+ } else if (0 < bkt.count) {
+ __CFBasicHashRemoveValue(ht, bkt.idx);
+ }
+ return bkt.count;
+}
+
+__private_extern__ CFIndex CFBasicHashRemoveValueAtIndex(CFBasicHashRef ht, CFIndex idx) {
+ if (!CFBasicHashIsMutable(ht)) HALT;
+ CFBasicHashBucket bkt = CFBasicHashGetBucket(ht, idx);
+ if (1 < bkt.count) {
+ ht->bits.mutations++;
+ if (ht->bits.counts_offset && bkt.count < LONG_MAX) { // if not as large as a CFIndex can be... otherwise clamp and do nothing
+ __CFBasicHashDecSlotCount(ht, bkt.idx);
+ }
+ } else if (0 < bkt.count) {
+ __CFBasicHashRemoveValue(ht, bkt.idx);
+ }
+ return bkt.count;
+}
+
+__private_extern__ 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) {
+ if (!CFBasicHashIsMutable(ht)) HALT;
+ if (__CFBasicHashSubABZero == stack_key) HALT;
+ if (__CFBasicHashSubABOne == stack_key) HALT;
+ if (__CFBasicHashSubABZero == int_value) HALT;
+ if (__CFBasicHashSubABOne == int_value) HALT;
+ CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key);
+ if (0 < bkt.count) {
+ ht->bits.mutations++;
+ } else {
+ // must rehash before renumbering
+ if (CFBasicHashGetCapacity(ht) < ht->bits.used_buckets + 1) {
+ __CFBasicHashRehash(ht, 1);
+ bkt.idx = __CFBasicHashFindBucket_NoCollision(ht, stack_key, 0);
+ }
+ CFIndex cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+ for (CFIndex idx = 0; idx < cnt; idx++) {
+ if (!__CFBasicHashIsEmptyOrDeleted(ht, idx)) {
+ uintptr_t stack_value = __CFBasicHashGetValue(ht, idx);
+ if (int_value <= stack_value) {
+ stack_value++;
+ __CFBasicHashSetValue(ht, idx, stack_value, true, false);
+ ht->bits.mutations++;
+ }
+ }
+ }
+ __CFBasicHashAddValue(ht, bkt.idx, stack_key, int_value);
+ return true;
+ }
+ return false;
+}
+
+void CFBasicHashRemoveIntValueAndDec(CFBasicHashRef ht, uintptr_t int_value) {
+ if (!CFBasicHashIsMutable(ht)) HALT;
+ if (__CFBasicHashSubABZero == int_value) HALT;
+ if (__CFBasicHashSubABOne == int_value) HALT;
+ uintptr_t bkt_idx = ~0UL;
+ CFIndex cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+ for (CFIndex idx = 0; idx < cnt; idx++) {
+ if (!__CFBasicHashIsEmptyOrDeleted(ht, idx)) {
+ uintptr_t stack_value = __CFBasicHashGetValue(ht, idx);
+ if (int_value == stack_value) {
+ bkt_idx = idx;
+ }
+ if (int_value < stack_value) {
+ stack_value--;
+ __CFBasicHashSetValue(ht, idx, stack_value, true, false);
+ ht->bits.mutations++;
+ }
+ }
+ }
+ __CFBasicHashRemoveValue(ht, bkt_idx);
+}
+
+__private_extern__ 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 *);
+ if (__CFBasicHashHasHashCache(ht)) size += sizeof(uintptr_t *);
+ if (total) {
+ CFIndex num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
+ if (0 < num_buckets) {
+ size += malloc_size(__CFBasicHashGetValues(ht));
+ 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) {
+ 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("%@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("%@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);
+ CFBasicHashApply(ht, ^(CFBasicHashBucket bkt) {
+ CFStringRef vDesc = NULL, kDesc = NULL;
+ if (!describeElements) {
+ vDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)bkt.weak_value);
+ if (ht->bits.keys_offset) {
+ kDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)bkt.weak_key);
+ }
+ } else {
+ vDesc = ht->callbacks->copyValueDescription(ht, bkt.weak_value);
+ if (ht->bits.keys_offset) {
+ kDesc = ht->callbacks->copyKeyDescription(ht, bkt.weak_key);
+ }
+ }
+ if (ht->bits.keys_offset && ht->bits.counts_offset) {
+ CFStringAppendFormat(result, NULL, CFSTR("%@%ld : %@ = %@ (%ld)\n"), entryPrefix, bkt.idx, kDesc, vDesc, bkt.count);
+ } else if (ht->bits.keys_offset) {
+ CFStringAppendFormat(result, NULL, CFSTR("%@%ld : %@ = %@\n"), entryPrefix, bkt.idx, kDesc, vDesc);
+ } else if (ht->bits.counts_offset) {
+ CFStringAppendFormat(result, NULL, CFSTR("%@%ld : %@ (%ld)\n"), entryPrefix, bkt.idx, vDesc, bkt.count);
+ } else {
+ CFStringAppendFormat(result, NULL, CFSTR("%@%ld : %@\n"), entryPrefix, bkt.idx, vDesc);
+ }
+ if (kDesc) CFRelease(kDesc);
+ if (vDesc) CFRelease(vDesc);
+ return (Boolean)true;
+ });
+ CFStringAppendFormat(result, NULL, CFSTR("%@}\n"), prefix);
+ return result;
+}
+
+__private_extern__ 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) {
+ 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) {
+ CFBasicHashRef ht = (CFBasicHashRef)cf;
+ return CFBasicHashGetCount(ht);
+}
+
+__private_extern__ CFStringRef __CFBasicHashCopyDescription(CFTypeRef cf) {
+ CFBasicHashRef ht = (CFBasicHashRef)cf;
+ CFStringRef desc = CFBasicHashCopyDescription(ht, false, CFSTR(""), CFSTR("\t"), true);
+ CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFBasicHash %p [%p]>%@"), cf, CFGetAllocator(cf), desc);
+ CFRelease(desc);
+ return result;
+}
+
+__private_extern__ void __CFBasicHashDeallocate(CFTypeRef cf) {
+ CFBasicHashRef ht = (CFBasicHashRef)cf;
+ if (ht->bits.finalized) HALT;
+ ht->bits.finalized = 1;
+ __CFBasicHashDrain(ht, true);
+#if ENABLE_MEMORY_COUNTERS
+ OSAtomicAdd64Barrier(-1, &__CFBasicHashTotalCount);
+ OSAtomicAdd32Barrier(-1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
+#endif
+}
+
+static CFTypeID __kCFBasicHashTypeID = _kCFRuntimeNotATypeID;
+
+static const CFRuntimeClass __CFBasicHashClass = {
+ _kCFRuntimeScannedObject,
+ "CFBasicHash",
+ NULL, // init
+ NULL, // copy
+ __CFBasicHashDeallocate,
+ __CFBasicHashEqual,
+ __CFBasicHashHash,
+ NULL, //
+ __CFBasicHashCopyDescription
+};
+
+__private_extern__ CFTypeID CFBasicHashGetTypeID(void) {
+ if (_kCFRuntimeNotATypeID == __kCFBasicHashTypeID) __kCFBasicHashTypeID = _CFRuntimeRegisterClass(&__CFBasicHashClass);
+ return __kCFBasicHashTypeID;
+}
+
+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
+ if (flags & kCFBasicHashHasHashCache) size += sizeof(uintptr_t *); // hashes
+ CFBasicHashRef ht = (CFBasicHashRef)_CFRuntimeCreateInstance(allocator, CFBasicHashGetTypeID(), size, NULL);
+ if (NULL == ht) return NULL;
+
+ ht->bits.finalized = 0;
+ ht->bits.hash_style = (flags >> 13) & 0x3;
+ ht->bits.fast_grow = (flags & kCFBasicHashAggressiveGrowth) ? 1 : 0;
+ ht->bits.counts_width = 0;
+ ht->bits.strong_values = (flags & kCFBasicHashStrongValues) ? 1 : 0;
+ ht->bits.strong_keys = (flags & kCFBasicHashStrongKeys) ? 1 : 0;
+ ht->bits.weak_values = (flags & kCFBasicHashWeakValues) ? 1 : 0;
+ ht->bits.weak_keys = (flags & kCFBasicHashWeakKeys) ? 1 : 0;
+ 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;
+ ht->bits.mutations = 1;
+
+ if (ht->bits.strong_values && ht->bits.weak_values) HALT;
+ if (ht->bits.strong_values && ht->bits.int_values) HALT;
+ if (ht->bits.strong_keys && ht->bits.weak_keys) HALT;
+ if (ht->bits.strong_keys && ht->bits.int_keys) HALT;
+ if (ht->bits.weak_values && ht->bits.int_values) HALT;
+ if (ht->bits.weak_keys && ht->bits.int_keys) HALT;
+ if (ht->bits.indirect_keys && ht->bits.strong_keys) HALT;
+ if (ht->bits.indirect_keys && ht->bits.weak_keys) HALT;
+ if (ht->bits.indirect_keys && ht->bits.int_keys) HALT;
+
+ uint64_t offset = 1;
+ ht->bits.keys_offset = (flags & kCFBasicHashHasKeys) ? offset++ : 0;
+ ht->bits.counts_offset = (flags & kCFBasicHashHasCounts) ? offset++ : 0;
+ ht->bits.hashes_offset = (flags & kCFBasicHashHasHashCache) ? offset++ : 0;
+
+#if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
+ ht->bits.hashes_offset = 0;
+ ht->bits.strong_values = 0;
+ ht->bits.strong_keys = 0;
+ ht->bits.weak_values = 0;
+ ht->bits.weak_keys = 0;
+#endif
+
+ __AssignWithWriteBarrier(&ht->callbacks, cb);
+ for (CFIndex idx = 0; idx < offset; idx++) {
+ ht->pointers[idx] = NULL;
+ }
+
+#if ENABLE_MEMORY_COUNTERS
+ int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
+ while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
+ int64_t count_now = OSAtomicAdd64Barrier(1, & __CFBasicHashTotalCount);
+ while (__CFBasicHashPeakCount < count_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakCount, count_now, & __CFBasicHashPeakCount));
+ OSAtomicAdd32Barrier(1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
+#endif
+
+ return ht;
+}
+
+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;
+ uintptr_t *new_hashes = NULL;
+
+ 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);
+ 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) {
+ new_keys = (CFBasicHashValue *)__CFBasicHashAllocateMemory2(allocator, new_num_buckets, sizeof(CFBasicHashValue), strongKeys, false);
+ if (!new_keys) return NULL; // in this unusual circumstance, leak previously allocated blocks for now
+ __SetLastAllocationEventName(new_keys, "CFBasicHash (key-store)");
+ }
+ if (src_ht->bits.counts_offset) {
+ new_counts = (uintptr_t *)__CFBasicHashAllocateMemory2(allocator, new_num_buckets, (1 << src_ht->bits.counts_width), false, false);
+ if (!new_counts) return NULL; // in this unusual circumstance, leak previously allocated blocks for now
+ __SetLastAllocationEventName(new_counts, "CFBasicHash (count-store)");
+ }
+ if (__CFBasicHashHasHashCache(src_ht)) {
+ new_hashes = (uintptr_t *)__CFBasicHashAllocateMemory2(allocator, new_num_buckets, sizeof(uintptr_t), false, false);
+ if (!new_hashes) return NULL; // in this unusual circumstance, leak previously allocated blocks for now
+ __SetLastAllocationEventName(new_hashes, "CFBasicHash (hash-store)");
+ }
+ }
+
+ CFBasicHashRef ht = (CFBasicHashRef)_CFRuntimeCreateInstance(allocator, CFBasicHashGetTypeID(), size, NULL);
+ if (NULL == ht) return NULL; // in this unusual circumstance, leak previously allocated blocks for now
+
+ memmove((uint8_t *)ht + sizeof(CFRuntimeBase), (uint8_t *)src_ht + sizeof(CFRuntimeBase), sizeof(ht->bits));
+ if (kCFUseCollectableAllocator && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+ ht->bits.strong_values = 0;
+ ht->bits.strong_keys = 0;
+ ht->bits.weak_values = 0;
+ ht->bits.weak_keys = 0;
+ }
+ ht->bits.finalized = 0;
+ ht->bits.mutations = 1;
+ __AssignWithWriteBarrier(&ht->callbacks, newcb);
+
+ if (0 == new_num_buckets) {
+#if ENABLE_MEMORY_COUNTERS
+ int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
+ while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
+ int64_t count_now = OSAtomicAdd64Barrier(1, & __CFBasicHashTotalCount);
+ while (__CFBasicHashPeakCount < count_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakCount, count_now, & __CFBasicHashPeakCount));
+ OSAtomicAdd32Barrier(1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
+#endif
+ return ht;
+ }
+
+ CFBasicHashValue *old_values = NULL, *old_keys = NULL;
+ void *old_counts = NULL;
+ uintptr_t *old_hashes = NULL;
+
+ old_values = __CFBasicHashGetValues(src_ht);
+ if (src_ht->bits.keys_offset) {
+ old_keys = __CFBasicHashGetKeys(src_ht);
+ }
+ if (src_ht->bits.counts_offset) {
+ old_counts = __CFBasicHashGetCounts(src_ht);
+ }
+ if (__CFBasicHashHasHashCache(src_ht)) {
+ old_hashes = __CFBasicHashGetHashes(src_ht);
+ }
+
+ __CFBasicHashSetValues(ht, new_values);
+ if (new_keys) {
+ __CFBasicHashSetKeys(ht, new_keys);
+ }
+ if (new_counts) {
+ __CFBasicHashSetCounts(ht, new_counts);
+ }
+ if (new_hashes) {
+ __CFBasicHashSetHashes(ht, new_hashes);
+ }
+
+ for (CFIndex idx = 0; idx < new_num_buckets; idx++) {
+ uintptr_t stack_value = old_values[idx].neutral;
+ if (stack_value != 0UL && stack_value != ~0UL) {
+ uintptr_t old_value = stack_value;
+ if (__CFBasicHashSubABZero == old_value) old_value = 0UL;
+ if (__CFBasicHashSubABOne == old_value) old_value = ~0UL;
+ __CFBasicHashSetValue(ht, idx, __CFBasicHashImportValue(ht, old_value), true, false);
+ if (new_keys) {
+ uintptr_t old_key = old_keys[idx].neutral;
+ if (__CFBasicHashSubABZero == old_key) old_key = 0UL;
+ if (__CFBasicHashSubABOne == old_key) old_key = ~0UL;
+ __CFBasicHashSetKey(ht, idx, __CFBasicHashImportKey(ht, old_key), true, false);
+ }
+ } else {
+ __CFBasicHashSetValue(ht, idx, stack_value, true, true);
+ if (new_keys) {
+ __CFBasicHashSetKey(ht, idx, stack_value, true, true);
+ }
+ }
+ }
+ if (new_counts) memmove(new_counts, old_counts, new_num_buckets * (1 << ht->bits.counts_width));
+ if (new_hashes) memmove(new_hashes, old_hashes, new_num_buckets * sizeof(uintptr_t));
+
+#if ENABLE_MEMORY_COUNTERS
+ int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
+ while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
+ int64_t count_now = OSAtomicAdd64Barrier(1, & __CFBasicHashTotalCount);
+ while (__CFBasicHashPeakCount < count_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakCount, count_now, & __CFBasicHashPeakCount));
+ OSAtomicAdd32Barrier(1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
+#endif
+
+ 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;
+}
+
*/
/* CFBasicHash.h
- Copyright (c) 2008-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2008-2012, Apple Inc. All rights reserved.
*/
#include <CoreFoundation/CFBase.h>
+++ /dev/null
-/*
- * Copyright (c) 2012 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@
- */
-
-/* CFBasicHash.m
- Copyright (c) 2008-2011, Apple Inc. All rights reserved.
- Responsibility: Christopher Kane
-*/
-
-#import "CFBasicHash.h"
-#import <CoreFoundation/CFRuntime.h>
-#import <CoreFoundation/CFSet.h>
-#import <Block.h>
-#import <math.h>
-
-#if DEPLOYMENT_TARGET_WINDOWS
-#define __SetLastAllocationEventName(A, B) do { } while (0)
-#else
-#define __SetLastAllocationEventName(A, B) do { if (__CFOASafe && (A)) __CFSetLastAllocationEventName(A, B); } 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
-#define ENABLE_MEMORY_COUNTERS 0
-
-#if defined(DTRACE_PROBES_DISABLED) && DTRACE_PROBES_DISABLED
-#undef ENABLE_DTRACE_PROBES
-#define ENABLE_DTRACE_PROBES 0
-#endif
-
-/*
-// dtrace -h -s foo.d
-// Note: output then changed by casts of the arguments
-// dtrace macros last generated 2010-09-08 on 10.7 prerelease (11A259)
-
-provider Cocoa_HashTable {
- probe hash_key(unsigned long table, unsigned long key, unsigned long hash);
- probe test_equal(unsigned long table, unsigned long key1, unsigned long key2);
- probe probing_start(unsigned long table, unsigned long num_buckets);
- probe probe_empty(unsigned long table, unsigned long idx);
- probe probe_deleted(unsigned long table, unsigned long idx);
- probe probe_valid(unsigned long table, unsigned long idx);
- probe probing_end(unsigned long table, unsigned long num_probes);
- probe rehash_start(unsigned long table, unsigned long num_buckets, unsigned long total_size);
- probe rehash_end(unsigned long table, unsigned long num_buckets, unsigned long total_size);
-};
-
-#pragma D attributes Unstable/Unstable/Common provider Cocoa_HashTable provider
-#pragma D attributes Private/Private/Unknown provider Cocoa_HashTable module
-#pragma D attributes Private/Private/Unknown provider Cocoa_HashTable function
-#pragma D attributes Unstable/Unstable/Common provider Cocoa_HashTable name
-#pragma D attributes Unstable/Unstable/Common provider Cocoa_HashTable args
-*/
-
-#if ENABLE_DTRACE_PROBES
-
-#define COCOA_HASHTABLE_STABILITY "___dtrace_stability$Cocoa_HashTable$v1$4_4_5_1_1_0_1_1_0_4_4_5_4_4_5"
-
-#define COCOA_HASHTABLE_TYPEDEFS "___dtrace_typedefs$Cocoa_HashTable$v2"
-
-#define COCOA_HASHTABLE_REHASH_END(arg0, arg1, arg2) \
-do { \
- __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
- __dtrace_probe$Cocoa_HashTable$rehash_end$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1), (unsigned long)(arg2)); \
- __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
-} while (0)
-#define COCOA_HASHTABLE_REHASH_END_ENABLED() \
- ({ int _r = __dtrace_isenabled$Cocoa_HashTable$rehash_end$v1(); \
- __asm__ volatile(""); \
- _r; })
-#define COCOA_HASHTABLE_REHASH_START(arg0, arg1, arg2) \
-do { \
- __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
- __dtrace_probe$Cocoa_HashTable$rehash_start$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1), (unsigned long)(arg2)); \
- __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
-} while (0)
-#define COCOA_HASHTABLE_REHASH_START_ENABLED() \
- ({ int _r = __dtrace_isenabled$Cocoa_HashTable$rehash_start$v1(); \
- __asm__ volatile(""); \
- _r; })
-#define COCOA_HASHTABLE_HASH_KEY(arg0, arg1, arg2) \
-do { \
- __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
- __dtrace_probe$Cocoa_HashTable$hash_key$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1), (unsigned long)(arg2)); \
- __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
-} while (0)
-#define COCOA_HASHTABLE_HASH_KEY_ENABLED() \
- ({ int _r = __dtrace_isenabled$Cocoa_HashTable$hash_key$v1(); \
- __asm__ volatile(""); \
- _r; })
-#define COCOA_HASHTABLE_PROBE_DELETED(arg0, arg1) \
-do { \
- __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
- __dtrace_probe$Cocoa_HashTable$probe_deleted$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
- __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
-} while (0)
-#define COCOA_HASHTABLE_PROBE_DELETED_ENABLED() \
- ({ int _r = __dtrace_isenabled$Cocoa_HashTable$probe_deleted$v1(); \
- __asm__ volatile(""); \
- _r; })
-#define COCOA_HASHTABLE_PROBE_EMPTY(arg0, arg1) \
-do { \
- __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
- __dtrace_probe$Cocoa_HashTable$probe_empty$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
- __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
-} while (0)
-#define COCOA_HASHTABLE_PROBE_EMPTY_ENABLED() \
- ({ int _r = __dtrace_isenabled$Cocoa_HashTable$probe_empty$v1(); \
- __asm__ volatile(""); \
- _r; })
-#define COCOA_HASHTABLE_PROBE_VALID(arg0, arg1) \
-do { \
- __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
- __dtrace_probe$Cocoa_HashTable$probe_valid$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
- __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
-} while (0)
-#define COCOA_HASHTABLE_PROBE_VALID_ENABLED() \
- ({ int _r = __dtrace_isenabled$Cocoa_HashTable$probe_valid$v1(); \
- __asm__ volatile(""); \
- _r; })
-#define COCOA_HASHTABLE_PROBING_END(arg0, arg1) \
-do { \
- __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
- __dtrace_probe$Cocoa_HashTable$probing_end$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
- __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
-} while (0)
-#define COCOA_HASHTABLE_PROBING_END_ENABLED() \
- ({ int _r = __dtrace_isenabled$Cocoa_HashTable$probing_end$v1(); \
- __asm__ volatile(""); \
- _r; })
-#define COCOA_HASHTABLE_PROBING_START(arg0, arg1) \
-do { \
- __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
- __dtrace_probe$Cocoa_HashTable$probing_start$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1)); \
- __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
-} while (0)
-#define COCOA_HASHTABLE_PROBING_START_ENABLED() \
- ({ int _r = __dtrace_isenabled$Cocoa_HashTable$probing_start$v1(); \
- __asm__ volatile(""); \
- _r; })
-#define COCOA_HASHTABLE_TEST_EQUAL(arg0, arg1, arg2) \
-do { \
- __asm__ volatile(".reference " COCOA_HASHTABLE_TYPEDEFS); \
- __dtrace_probe$Cocoa_HashTable$test_equal$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67((unsigned long)(arg0), (unsigned long)(arg1), (unsigned long)(arg2)); \
- __asm__ volatile(".reference " COCOA_HASHTABLE_STABILITY); \
-} while (0)
-#define COCOA_HASHTABLE_TEST_EQUAL_ENABLED() \
- ({ int _r = __dtrace_isenabled$Cocoa_HashTable$test_equal$v1(); \
- __asm__ volatile(""); \
- _r; })
-
-extern void __dtrace_probe$Cocoa_HashTable$hash_key$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long, unsigned long);
-extern int __dtrace_isenabled$Cocoa_HashTable$hash_key$v1(void);
-extern void __dtrace_probe$Cocoa_HashTable$probe_deleted$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
-extern int __dtrace_isenabled$Cocoa_HashTable$probe_deleted$v1(void);
-extern void __dtrace_probe$Cocoa_HashTable$probe_empty$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
-extern int __dtrace_isenabled$Cocoa_HashTable$probe_empty$v1(void);
-extern void __dtrace_probe$Cocoa_HashTable$probe_valid$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
-extern int __dtrace_isenabled$Cocoa_HashTable$probe_valid$v1(void);
-extern void __dtrace_probe$Cocoa_HashTable$probing_end$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
-extern int __dtrace_isenabled$Cocoa_HashTable$probing_end$v1(void);
-extern void __dtrace_probe$Cocoa_HashTable$probing_start$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long);
-extern int __dtrace_isenabled$Cocoa_HashTable$probing_start$v1(void);
-extern void __dtrace_probe$Cocoa_HashTable$rehash_end$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long, unsigned long);
-extern int __dtrace_isenabled$Cocoa_HashTable$rehash_end$v1(void);
-extern void __dtrace_probe$Cocoa_HashTable$rehash_start$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long, unsigned long);
-extern int __dtrace_isenabled$Cocoa_HashTable$rehash_start$v1(void);
-extern void __dtrace_probe$Cocoa_HashTable$test_equal$v1$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67$756e7369676e6564206c6f6e67(unsigned long, unsigned long, unsigned long);
-extern int __dtrace_isenabled$Cocoa_HashTable$test_equal$v1(void);
-
-#else
-
-#define COCOA_HASHTABLE_REHASH_END(arg0, arg1, arg2) do {} while (0)
-#define COCOA_HASHTABLE_REHASH_END_ENABLED() 0
-#define COCOA_HASHTABLE_REHASH_START(arg0, arg1, arg2) do {} while (0)
-#define COCOA_HASHTABLE_REHASH_START_ENABLED() 0
-#define COCOA_HASHTABLE_HASH_KEY(arg0, arg1, arg2) do {} while (0)
-#define COCOA_HASHTABLE_HASH_KEY_ENABLED() 0
-#define COCOA_HASHTABLE_PROBE_DELETED(arg0, arg1) do {} while (0)
-#define COCOA_HASHTABLE_PROBE_DELETED_ENABLED() 0
-#define COCOA_HASHTABLE_PROBE_EMPTY(arg0, arg1) do {} while (0)
-#define COCOA_HASHTABLE_PROBE_EMPTY_ENABLED() 0
-#define COCOA_HASHTABLE_PROBE_VALID(arg0, arg1) do {} while (0)
-#define COCOA_HASHTABLE_PROBE_VALID_ENABLED() 0
-#define COCOA_HASHTABLE_PROBING_END(arg0, arg1) do {} while (0)
-#define COCOA_HASHTABLE_PROBING_END_ENABLED() 0
-#define COCOA_HASHTABLE_PROBING_START(arg0, arg1) do {} while (0)
-#define COCOA_HASHTABLE_PROBING_START_ENABLED() 0
-#define COCOA_HASHTABLE_TEST_EQUAL(arg0, arg1, arg2) do {} while (0)
-#define COCOA_HASHTABLE_TEST_EQUAL_ENABLED() 0
-
-#endif
-
-
-#if !defined(__LP64__)
-#define __LP64__ 0
-#endif
-
-// Prime numbers. Values above 100 have been adjusted up so that the
-// malloced block size will be just below a multiple of 512; values
-// above 1200 have been adjusted up to just below a multiple of 4096.
-static const uintptr_t __CFBasicHashTableSizes[64] = {
- 0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723,
- 2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607,
- 214519, 346607, 561109, 907759, 1468927, 2376191, 3845119,
- 6221311, 10066421, 16287743, 26354171, 42641881, 68996069,
- 111638519, 180634607, 292272623, 472907251,
-#if __LP64__
- 765180413UL, 1238087663UL, 2003267557UL, 3241355263UL, 5244622819UL,
-#if 0
- 8485977589UL, 13730600407UL, 22216578047UL, 35947178479UL,
- 58163756537UL, 94110934997UL, 152274691561UL, 246385626107UL,
- 398660317687UL, 645045943807UL, 1043706260983UL, 1688752204787UL,
- 2732458465769UL, 4421210670577UL, 7153669136377UL,
- 11574879807461UL, 18728548943849UL, 30303428750843UL
-#endif
-#endif
-};
-
-static const uintptr_t __CFBasicHashTableCapacities[64] = {
- 0, 3, 6, 11, 19, 32, 52, 85, 118, 155, 237, 390, 672, 1065,
- 1732, 2795, 4543, 7391, 12019, 19302, 31324, 50629, 81956,
- 132580, 214215, 346784, 561026, 907847, 1468567, 2376414,
- 3844982, 6221390, 10066379, 16287773, 26354132, 42641916,
- 68996399, 111638327, 180634415, 292272755,
-#if __LP64__
- 472907503UL, 765180257UL, 1238087439UL, 2003267722UL, 3241355160UL,
-#if 0
- 5244622578UL, 8485977737UL, 13730600347UL, 22216578100UL,
- 35947178453UL, 58163756541UL, 94110935011UL, 152274691274UL,
- 246385626296UL, 398660317578UL, 645045943559UL, 1043706261135UL,
- 1688752204693UL, 2732458465840UL, 4421210670552UL,
- 7153669136706UL, 11574879807265UL, 18728548943682UL
-#endif
-#endif
-};
-
-// Primitive roots for the primes above
-static const uintptr_t __CFBasicHashPrimitiveRoots[64] = {
- 0, 2, 3, 2, 5, 6, 7, 3, 19, 6, 5, 3, 3, 3,
- 2, 5, 6, 3, 3, 6, 2, 3, 3,
- 3, 5, 10, 3, 3, 22, 3,
- 3, 3, 5, 2, 22, 2,
- 11, 5, 5, 2,
-#if __LP64__
- 3, 10, 2, 3, 10,
- 2, 3, 5, 3,
- 3, 2, 7, 2,
- 3, 3, 3, 2,
- 3, 5, 5,
- 2, 3, 2
-#endif
-};
-
-CF_INLINE void *__CFBasicHashAllocateMemory(CFConstBasicHashRef ht, CFIndex count, CFIndex elem_size, Boolean strong, Boolean compactable) {
- CFAllocatorRef allocator = CFGetAllocator(ht);
- void *new_mem = NULL;
- if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
- new_mem = auto_zone_allocate_object(objc_collectableZone(), count * elem_size, strong ? (compactable ? AUTO_POINTERS_ONLY : AUTO_MEMORY_SCANNED) : AUTO_UNSCANNED, false, false);
- } else {
- new_mem = CFAllocatorAllocate(allocator, count * elem_size, 0);
- }
- if (!new_mem) HALT;
- return new_mem;
-}
-
-#define __CFBasicHashSubABZero 0xa7baadb1
-#define __CFBasicHashSubABOne 0xa5baadb9
-
-typedef union {
- uintptr_t neutral;
- id strong;
- id weak;
-} CFBasicHashValue;
-
-struct __CFBasicHash {
- CFRuntimeBase base;
- struct { // 128 bits
- 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;
- uint8_t hashes_offset:2;
- uint8_t strong_values:1;
- uint8_t strong_keys:1;
- uint8_t weak_values:1;
- uint8_t weak_keys:1;
- 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;
- } bits;
- __strong CFBasicHashCallbacks *callbacks;
- void *pointers[1];
-};
-
-__private_extern__ Boolean CFBasicHashHasStrongValues(CFConstBasicHashRef ht) {
-#if defined(__arm__)
- return false;
-#else
- return ht->bits.strong_values ? true : false;
-#endif
-}
-
-__private_extern__ Boolean CFBasicHashHasStrongKeys(CFConstBasicHashRef ht) {
-#if defined(__arm__)
- return false;
-#else
- return ht->bits.strong_keys ? true : false;
-#endif
-}
-
-CF_INLINE Boolean __CFBasicHashHasCompactableKeys(CFConstBasicHashRef ht) {
-#if defined(__arm__)
- return false;
-#else
- return ht->bits.compactable_keys ? true : false;
-#endif
-}
-
-CF_INLINE Boolean __CFBasicHashHasCompactableValues(CFConstBasicHashRef ht) {
-#if defined(__arm__)
- return false;
-#else
- return ht->bits.compactable_values ? true : false;
-#endif
-}
-
-CF_INLINE Boolean __CFBasicHashHasWeakValues(CFConstBasicHashRef ht) {
-#if defined(__arm__)
- return false;
-#else
- return ht->bits.weak_values ? true : false;
-#endif
-}
-
-CF_INLINE Boolean __CFBasicHashHasWeakKeys(CFConstBasicHashRef ht) {
-#if defined(__arm__)
- return false;
-#else
- return ht->bits.weak_keys ? true : false;
-#endif
-}
-
-CF_INLINE Boolean __CFBasicHashHasHashCache(CFConstBasicHashRef ht) {
-#if defined(__arm__)
- return false;
-#else
- return ht->bits.hashes_offset ? true : false;
-#endif
-}
-
-CF_INLINE uintptr_t __CFBasicHashImportValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
- return ht->callbacks->retainValue(ht, stack_value);
-}
-
-CF_INLINE uintptr_t __CFBasicHashImportKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
- return ht->callbacks->retainKey(ht, stack_key);
-}
-
-CF_INLINE void __CFBasicHashEjectValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
- ht->callbacks->releaseValue(ht, stack_value);
-}
-
-CF_INLINE void __CFBasicHashEjectKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
- ht->callbacks->releaseKey(ht, 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);
-}
-
-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);
-}
-
-CF_INLINE CFHashCode __CFBasicHashHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
- CFHashCode hash_code = (CFHashCode)ht->callbacks->hashKey(ht, stack_key);
- COCOA_HASHTABLE_HASH_KEY(ht, stack_key, hash_code);
- return hash_code;
-}
-
-CF_INLINE CFBasicHashValue *__CFBasicHashGetValues(CFConstBasicHashRef ht) {
- return (CFBasicHashValue *)ht->pointers[0];
-}
-
-CF_INLINE void __CFBasicHashSetValues(CFBasicHashRef ht, CFBasicHashValue *ptr) {
- __AssignWithWriteBarrier(&ht->pointers[0], ptr);
-}
-
-CF_INLINE CFBasicHashValue *__CFBasicHashGetKeys(CFConstBasicHashRef ht) {
- return (CFBasicHashValue *)ht->pointers[ht->bits.keys_offset];
-}
-
-CF_INLINE void __CFBasicHashSetKeys(CFBasicHashRef ht, CFBasicHashValue *ptr) {
- __AssignWithWriteBarrier(&ht->pointers[ht->bits.keys_offset], ptr);
-}
-
-CF_INLINE void *__CFBasicHashGetCounts(CFConstBasicHashRef ht) {
- return (void *)ht->pointers[ht->bits.counts_offset];
-}
-
-CF_INLINE void __CFBasicHashSetCounts(CFBasicHashRef ht, void *ptr) {
- __AssignWithWriteBarrier(&ht->pointers[ht->bits.counts_offset], ptr);
-}
-
-CF_INLINE uintptr_t __CFBasicHashGetValue(CFConstBasicHashRef ht, CFIndex idx) {
- uintptr_t val = __CFBasicHashGetValues(ht)[idx].neutral;
- if (__CFBasicHashSubABZero == val) return 0UL;
- if (__CFBasicHashSubABOne == val) return ~0UL;
- return val;
-}
-
-CF_INLINE void __CFBasicHashSetValue(CFBasicHashRef ht, CFIndex idx, uintptr_t stack_value, Boolean ignoreOld, Boolean literal) {
- CFBasicHashValue *valuep = &(__CFBasicHashGetValues(ht)[idx]);
- uintptr_t old_value = ignoreOld ? 0 : valuep->neutral;
- if (!literal) {
- if (0UL == stack_value) stack_value = __CFBasicHashSubABZero;
- if (~0UL == stack_value) stack_value = __CFBasicHashSubABOne;
- }
- if (CFBasicHashHasStrongValues(ht)) valuep->strong = (id)stack_value; else valuep->neutral = stack_value;
- if (!ignoreOld) {
- if (!(old_value == 0UL || old_value == ~0UL)) {
- if (__CFBasicHashSubABZero == old_value) old_value = 0UL;
- if (__CFBasicHashSubABOne == old_value) old_value = ~0UL;
- __CFBasicHashEjectValue(ht, old_value);
- }
- }
-}
-
-CF_INLINE uintptr_t __CFBasicHashGetKey(CFConstBasicHashRef ht, CFIndex idx) {
- if (ht->bits.keys_offset) {
- uintptr_t key = __CFBasicHashGetKeys(ht)[idx].neutral;
- if (__CFBasicHashSubABZero == key) return 0UL;
- if (__CFBasicHashSubABOne == key) return ~0UL;
- return key;
- }
- if (ht->bits.indirect_keys) {
- uintptr_t stack_value = __CFBasicHashGetValue(ht, idx);
- return ht->callbacks->getIndirectKey(ht, stack_value);
- }
- return __CFBasicHashGetValue(ht, idx);
-}
-
-CF_INLINE void __CFBasicHashSetKey(CFBasicHashRef ht, CFIndex idx, uintptr_t stack_key, Boolean ignoreOld, Boolean literal) {
- if (0 == ht->bits.keys_offset) HALT;
- CFBasicHashValue *keyp = &(__CFBasicHashGetKeys(ht)[idx]);
- uintptr_t old_key = ignoreOld ? 0 : keyp->neutral;
- if (!literal) {
- if (0UL == stack_key) stack_key = __CFBasicHashSubABZero;
- if (~0UL == stack_key) stack_key = __CFBasicHashSubABOne;
- }
- if (CFBasicHashHasStrongKeys(ht)) keyp->strong = (id)stack_key; else keyp->neutral = stack_key;
- if (!ignoreOld) {
- if (!(old_key == 0UL || old_key == ~0UL)) {
- if (__CFBasicHashSubABZero == old_key) old_key = 0UL;
- if (__CFBasicHashSubABOne == old_key) old_key = ~0UL;
- __CFBasicHashEjectKey(ht, old_key);
- }
- }
-}
-
-CF_INLINE uintptr_t __CFBasicHashIsEmptyOrDeleted(CFConstBasicHashRef ht, CFIndex idx) {
- uintptr_t stack_value = __CFBasicHashGetValues(ht)[idx].neutral;
- return (0UL == stack_value || ~0UL == stack_value);
-}
-
-CF_INLINE uintptr_t __CFBasicHashIsDeleted(CFConstBasicHashRef ht, CFIndex idx) {
- uintptr_t stack_value = __CFBasicHashGetValues(ht)[idx].neutral;
- return (~0UL == stack_value);
-}
-
-CF_INLINE uintptr_t __CFBasicHashGetSlotCount(CFConstBasicHashRef ht, CFIndex idx) {
- void *counts = __CFBasicHashGetCounts(ht);
- switch (ht->bits.counts_width) {
- case 0: return ((uint8_t *)counts)[idx];
- case 1: return ((uint16_t *)counts)[idx];
- case 2: return ((uint32_t *)counts)[idx];
- case 3: return ((uint64_t *)counts)[idx];
- }
- return 0;
-}
-
-CF_INLINE void __CFBasicHashBumpCounts(CFBasicHashRef ht) {
- void *counts = __CFBasicHashGetCounts(ht);
- CFAllocatorRef allocator = CFGetAllocator(ht);
- switch (ht->bits.counts_width) {
- case 0: {
- uint8_t *counts08 = (uint8_t *)counts;
- ht->bits.counts_width = 1;
- CFIndex num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
- uint16_t *counts16 = (uint16_t *)__CFBasicHashAllocateMemory(ht, num_buckets, 2, false, false);
- __SetLastAllocationEventName(counts16, "CFBasicHash (count-store)");
- for (CFIndex idx2 = 0; idx2 < num_buckets; idx2++) {
- counts16[idx2] = counts08[idx2];
- }
- __CFBasicHashSetCounts(ht, counts16);
- if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
- CFAllocatorDeallocate(allocator, counts08);
- }
- break;
- }
- case 1: {
- uint16_t *counts16 = (uint16_t *)counts;
- ht->bits.counts_width = 2;
- CFIndex num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
- uint32_t *counts32 = (uint32_t *)__CFBasicHashAllocateMemory(ht, num_buckets, 4, false, false);
- __SetLastAllocationEventName(counts32, "CFBasicHash (count-store)");
- for (CFIndex idx2 = 0; idx2 < num_buckets; idx2++) {
- counts32[idx2] = counts16[idx2];
- }
- __CFBasicHashSetCounts(ht, counts32);
- if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
- CFAllocatorDeallocate(allocator, counts16);
- }
- break;
- }
- case 2: {
- uint32_t *counts32 = (uint32_t *)counts;
- ht->bits.counts_width = 3;
- CFIndex num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
- uint64_t *counts64 = (uint64_t *)__CFBasicHashAllocateMemory(ht, num_buckets, 8, false, false);
- __SetLastAllocationEventName(counts64, "CFBasicHash (count-store)");
- for (CFIndex idx2 = 0; idx2 < num_buckets; idx2++) {
- counts64[idx2] = counts32[idx2];
- }
- __CFBasicHashSetCounts(ht, counts64);
- if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
- CFAllocatorDeallocate(allocator, counts32);
- }
- break;
- }
- case 3: {
- HALT;
- break;
- }
- }
-}
-
-static void __CFBasicHashIncSlotCount(CFBasicHashRef ht, CFIndex idx) {
- void *counts = __CFBasicHashGetCounts(ht);
- switch (ht->bits.counts_width) {
- case 0: {
- uint8_t *counts08 = (uint8_t *)counts;
- uint8_t val = counts08[idx];
- if (val < INT8_MAX) {
- counts08[idx] = val + 1;
- return;
- }
- __CFBasicHashBumpCounts(ht);
- __CFBasicHashIncSlotCount(ht, idx);
- break;
- }
- case 1: {
- uint16_t *counts16 = (uint16_t *)counts;
- uint16_t val = counts16[idx];
- if (val < INT16_MAX) {
- counts16[idx] = val + 1;
- return;
- }
- __CFBasicHashBumpCounts(ht);
- __CFBasicHashIncSlotCount(ht, idx);
- break;
- }
- case 2: {
- uint32_t *counts32 = (uint32_t *)counts;
- uint32_t val = counts32[idx];
- if (val < INT32_MAX) {
- counts32[idx] = val + 1;
- return;
- }
- __CFBasicHashBumpCounts(ht);
- __CFBasicHashIncSlotCount(ht, idx);
- break;
- }
- case 3: {
- uint64_t *counts64 = (uint64_t *)counts;
- uint64_t val = counts64[idx];
- if (val < INT64_MAX) {
- counts64[idx] = val + 1;
- return;
- }
- __CFBasicHashBumpCounts(ht);
- __CFBasicHashIncSlotCount(ht, idx);
- break;
- }
- }
-}
-
-CF_INLINE void __CFBasicHashDecSlotCount(CFBasicHashRef ht, CFIndex idx) {
- void *counts = __CFBasicHashGetCounts(ht);
- switch (ht->bits.counts_width) {
- case 0: ((uint8_t *)counts)[idx]--; return;
- case 1: ((uint16_t *)counts)[idx]--; return;
- case 2: ((uint32_t *)counts)[idx]--; return;
- case 3: ((uint64_t *)counts)[idx]--; return;
- }
-}
-
-CF_INLINE uintptr_t *__CFBasicHashGetHashes(CFConstBasicHashRef ht) {
- return (uintptr_t *)ht->pointers[ht->bits.hashes_offset];
-}
-
-CF_INLINE void __CFBasicHashSetHashes(CFBasicHashRef ht, uintptr_t *ptr) {
- __AssignWithWriteBarrier(&ht->pointers[ht->bits.hashes_offset], ptr);
-}
-
-
-// to expose the load factor, expose this function to customization
-CF_INLINE CFIndex __CFBasicHashGetCapacityForNumBuckets(CFConstBasicHashRef ht, CFIndex num_buckets_idx) {
- return __CFBasicHashTableCapacities[num_buckets_idx];
-}
-
-CF_INLINE CFIndex __CFBasicHashGetNumBucketsIndexForCapacity(CFConstBasicHashRef ht, CFIndex capacity) {
- for (CFIndex idx = 0; idx < 64; idx++) {
- if (capacity <= __CFBasicHashGetCapacityForNumBuckets(ht, idx)) return idx;
- }
- HALT;
- return 0;
-}
-
-__private_extern__ CFIndex CFBasicHashGetNumBuckets(CFConstBasicHashRef ht) {
- return __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
-}
-
-__private_extern__ CFIndex CFBasicHashGetCapacity(CFConstBasicHashRef ht) {
- return __CFBasicHashGetCapacityForNumBuckets(ht, ht->bits.num_buckets_idx);
-}
-
-// In returned struct, .count is zero if the bucket is empty or deleted,
-// and the .weak_key field indicates which. .idx is either the index of
-// 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) {
- CFBasicHashBucket result;
- result.idx = idx;
- if (__CFBasicHashIsEmptyOrDeleted(ht, idx)) {
- result.count = 0;
- result.weak_value = 0;
- result.weak_key = 0;
- } else {
- result.count = (ht->bits.counts_offset) ? __CFBasicHashGetSlotCount(ht, idx) : 1;
- result.weak_value = __CFBasicHashGetValue(ht, idx);
- result.weak_key = __CFBasicHashGetKey(ht, idx);
- }
- return result;
-}
-
-#if defined(__arm__)
-static uintptr_t __CFBasicHashFold(uintptr_t dividend, uint8_t idx) {
- switch (idx) {
- case 1: return dividend % 3;
- case 2: return dividend % 7;
- case 3: return dividend % 13;
- case 4: return dividend % 23;
- case 5: return dividend % 41;
- case 6: return dividend % 71;
- case 7: return dividend % 127;
- case 8: return dividend % 191;
- case 9: return dividend % 251;
- case 10: return dividend % 383;
- case 11: return dividend % 631;
- case 12: return dividend % 1087;
- case 13: return dividend % 1723;
- case 14: return dividend % 2803;
- case 15: return dividend % 4523;
- case 16: return dividend % 7351;
- case 17: return dividend % 11959;
- case 18: return dividend % 19447;
- case 19: return dividend % 31231;
- case 20: return dividend % 50683;
- case 21: return dividend % 81919;
- case 22: return dividend % 132607;
- case 23: return dividend % 214519;
- case 24: return dividend % 346607;
- case 25: return dividend % 561109;
- case 26: return dividend % 907759;
- case 27: return dividend % 1468927;
- case 28: return dividend % 2376191;
- case 29: return dividend % 3845119;
- case 30: return dividend % 6221311;
- case 31: return dividend % 10066421;
- case 32: return dividend % 16287743;
- case 33: return dividend % 26354171;
- case 34: return dividend % 42641881;
- case 35: return dividend % 68996069;
- case 36: return dividend % 111638519;
- case 37: return dividend % 180634607;
- case 38: return dividend % 292272623;
- case 39: return dividend % 472907251;
- }
- HALT;
- return ~0;
-}
-#endif
-
-
-#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Linear
-#define FIND_BUCKET_HASH_STYLE 1
-#define FIND_BUCKET_FOR_REHASH 0
-#define FIND_BUCKET_FOR_INDIRECT_KEY 0
-#include "CFBasicHashFindBucket.m"
-
-#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Linear_NoCollision
-#define FIND_BUCKET_HASH_STYLE 1
-#define FIND_BUCKET_FOR_REHASH 1
-#define FIND_BUCKET_FOR_INDIRECT_KEY 0
-#include "CFBasicHashFindBucket.m"
-
-#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Linear_Indirect
-#define FIND_BUCKET_HASH_STYLE 1
-#define FIND_BUCKET_FOR_REHASH 0
-#define FIND_BUCKET_FOR_INDIRECT_KEY 1
-#include "CFBasicHashFindBucket.m"
-
-#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Linear_Indirect_NoCollision
-#define FIND_BUCKET_HASH_STYLE 1
-#define FIND_BUCKET_FOR_REHASH 1
-#define FIND_BUCKET_FOR_INDIRECT_KEY 1
-#include "CFBasicHashFindBucket.m"
-
-#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Double
-#define FIND_BUCKET_HASH_STYLE 2
-#define FIND_BUCKET_FOR_REHASH 0
-#define FIND_BUCKET_FOR_INDIRECT_KEY 0
-#include "CFBasicHashFindBucket.m"
-
-#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Double_NoCollision
-#define FIND_BUCKET_HASH_STYLE 2
-#define FIND_BUCKET_FOR_REHASH 1
-#define FIND_BUCKET_FOR_INDIRECT_KEY 0
-#include "CFBasicHashFindBucket.m"
-
-#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Double_Indirect
-#define FIND_BUCKET_HASH_STYLE 2
-#define FIND_BUCKET_FOR_REHASH 0
-#define FIND_BUCKET_FOR_INDIRECT_KEY 1
-#include "CFBasicHashFindBucket.m"
-
-#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Double_Indirect_NoCollision
-#define FIND_BUCKET_HASH_STYLE 2
-#define FIND_BUCKET_FOR_REHASH 1
-#define FIND_BUCKET_FOR_INDIRECT_KEY 1
-#include "CFBasicHashFindBucket.m"
-
-#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Exponential
-#define FIND_BUCKET_HASH_STYLE 3
-#define FIND_BUCKET_FOR_REHASH 0
-#define FIND_BUCKET_FOR_INDIRECT_KEY 0
-#include "CFBasicHashFindBucket.m"
-
-#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Exponential_NoCollision
-#define FIND_BUCKET_HASH_STYLE 3
-#define FIND_BUCKET_FOR_REHASH 1
-#define FIND_BUCKET_FOR_INDIRECT_KEY 0
-#include "CFBasicHashFindBucket.m"
-
-#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Exponential_Indirect
-#define FIND_BUCKET_HASH_STYLE 3
-#define FIND_BUCKET_FOR_REHASH 0
-#define FIND_BUCKET_FOR_INDIRECT_KEY 1
-#include "CFBasicHashFindBucket.m"
-
-#define FIND_BUCKET_NAME ___CFBasicHashFindBucket_Exponential_Indirect_NoCollision
-#define FIND_BUCKET_HASH_STYLE 3
-#define FIND_BUCKET_FOR_REHASH 1
-#define FIND_BUCKET_FOR_INDIRECT_KEY 1
-#include "CFBasicHashFindBucket.m"
-
-
-CF_INLINE CFBasicHashBucket __CFBasicHashFindBucket(CFConstBasicHashRef ht, uintptr_t stack_key) {
- if (0 == ht->bits.num_buckets_idx) {
- CFBasicHashBucket result = {kCFNotFound, 0UL, 0UL, 0};
- return result;
- }
- if (ht->bits.indirect_keys) {
- switch (ht->bits.hash_style) {
- case __kCFBasicHashLinearHashingValue: return ___CFBasicHashFindBucket_Linear_Indirect(ht, stack_key);
- case __kCFBasicHashDoubleHashingValue: return ___CFBasicHashFindBucket_Double_Indirect(ht, stack_key);
- case __kCFBasicHashExponentialHashingValue: return ___CFBasicHashFindBucket_Exponential_Indirect(ht, stack_key);
- }
- } else {
- switch (ht->bits.hash_style) {
- case __kCFBasicHashLinearHashingValue: return ___CFBasicHashFindBucket_Linear(ht, stack_key);
- case __kCFBasicHashDoubleHashingValue: return ___CFBasicHashFindBucket_Double(ht, stack_key);
- case __kCFBasicHashExponentialHashingValue: return ___CFBasicHashFindBucket_Exponential(ht, stack_key);
- }
- }
- HALT;
- CFBasicHashBucket result = {kCFNotFound, 0UL, 0UL, 0};
- return result;
-}
-
-CF_INLINE CFIndex __CFBasicHashFindBucket_NoCollision(CFConstBasicHashRef ht, uintptr_t stack_key, uintptr_t key_hash) {
- if (0 == ht->bits.num_buckets_idx) {
- return kCFNotFound;
- }
- if (ht->bits.indirect_keys) {
- switch (ht->bits.hash_style) {
- case __kCFBasicHashLinearHashingValue: return ___CFBasicHashFindBucket_Linear_Indirect_NoCollision(ht, stack_key, key_hash);
- case __kCFBasicHashDoubleHashingValue: return ___CFBasicHashFindBucket_Double_Indirect_NoCollision(ht, stack_key, key_hash);
- case __kCFBasicHashExponentialHashingValue: return ___CFBasicHashFindBucket_Exponential_Indirect_NoCollision(ht, stack_key, key_hash);
- }
- } else {
- switch (ht->bits.hash_style) {
- case __kCFBasicHashLinearHashingValue: return ___CFBasicHashFindBucket_Linear_NoCollision(ht, stack_key, key_hash);
- case __kCFBasicHashDoubleHashingValue: return ___CFBasicHashFindBucket_Double_NoCollision(ht, stack_key, key_hash);
- case __kCFBasicHashExponentialHashingValue: return ___CFBasicHashFindBucket_Exponential_NoCollision(ht, stack_key, key_hash);
- }
- }
- HALT;
- return kCFNotFound;
-}
-
-__private_extern__ CFBasicHashBucket CFBasicHashFindBucket(CFConstBasicHashRef ht, uintptr_t stack_key) {
- if (__CFBasicHashSubABZero == stack_key || __CFBasicHashSubABOne == stack_key) {
- CFBasicHashBucket result = {kCFNotFound, 0UL, 0UL, 0};
- return result;
- }
- return __CFBasicHashFindBucket(ht, stack_key);
-}
-
-__private_extern__ uint16_t CFBasicHashGetSpecialBits(CFConstBasicHashRef ht) {
- return ht->bits.special_bits;
-}
-
-__private_extern__ uint16_t CFBasicHashSetSpecialBits(CFBasicHashRef ht, uint16_t bits) {
- uint16_t old = ht->bits.special_bits;
- ht->bits.special_bits = bits;
- return old;
-}
-
-__private_extern__ 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;
- if (__CFBasicHashHasHashCache(ht)) flags |= kCFBasicHashHasHashCache;
- return flags;
-}
-
-__private_extern__ const CFBasicHashCallbacks *CFBasicHashGetCallbacks(CFConstBasicHashRef ht) {
- return ht->callbacks;
-}
-
-__private_extern__ CFIndex CFBasicHashGetCount(CFConstBasicHashRef ht) {
- if (ht->bits.counts_offset) {
- CFIndex total = 0L;
- CFIndex cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx];
- for (CFIndex idx = 0; idx < cnt; idx++) {
- total += __CFBasicHashGetSlotCount(ht, idx);
- }
- return total;
- }
- return (CFIndex)ht->bits.used_buckets;
-}
-
-__private_extern__ CFIndex CFBasicHashGetCountOfKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
- if (__CFBasicHashSubABZero == stack_key || __CFBasicHashSubABOne == stack_key) {
- return 0L;
- }
- if (0L == ht->bits.used_buckets) {
- return 0L;
- }
- return __CFBasicHashFindBucket(ht, stack_key).count;
-}
-
-__private_extern__ CFIndex CFBasicHashGetCountOfValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
- if (__CFBasicHashSubABZero == stack_value) {
- return 0L;
- }
- if (0L == ht->bits.used_buckets) {
- return 0L;
- }
- if (!(ht->bits.keys_offset)) {
- return __CFBasicHashFindBucket(ht, stack_value).count;
- }
- __block CFIndex total = 0L;
- CFBasicHashApply(ht, ^(CFBasicHashBucket bkt) {
- if ((stack_value == bkt.weak_value) || __CFBasicHashTestEqualValue(ht, bkt.weak_value, stack_value)) total += bkt.count;
- return (Boolean)true;
- });
- return total;
-}
-
-__private_extern__ Boolean CFBasicHashesAreEqual(CFConstBasicHashRef ht1, CFConstBasicHashRef ht2) {
- CFIndex cnt1 = CFBasicHashGetCount(ht1);
- if (cnt1 != CFBasicHashGetCount(ht2)) return false;
- if (0 == cnt1) return true;
- __block Boolean equal = true;
- CFBasicHashApply(ht1, ^(CFBasicHashBucket bkt1) {
- CFBasicHashBucket bkt2 = __CFBasicHashFindBucket(ht2, bkt1.weak_key);
- if (bkt1.count != bkt2.count) {
- equal = false;
- return (Boolean)false;
- }
- if ((ht1->bits.keys_offset) && (bkt1.weak_value != bkt2.weak_value) && !__CFBasicHashTestEqualValue(ht1, bkt1.weak_value, bkt2.weak_value)) {
- equal = false;
- return (Boolean)false;
- }
- return (Boolean)true;
- });
- return equal;
-}
-
-__private_extern__ 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);
- if (0 < bkt.count) {
- if (!block(bkt)) {
- return;
- }
- used--;
- }
- }
-}
-
-__private_extern__ 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];
- if (cnt < range.location + range.length) HALT;
- for (CFIndex idx = 0; idx < range.length; idx++) {
- CFBasicHashBucket bkt = CFBasicHashGetBucket(ht, range.location + idx);
- if (0 < bkt.count) {
- if (!block(bkt)) {
- return;
- }
- }
- }
-}
-
-__private_extern__ 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++) {
- CFBasicHashBucket bkt = CFBasicHashGetBucket(ht, idx);
- if (0 < bkt.count) {
- used--;
- for (CFIndex cnt = bkt.count; cnt-- && offset < bufferslen;) {
- if (weak_values) { weak_values[offset] = bkt.weak_value; }
- if (weak_keys) { weak_keys[offset] = bkt.weak_key; }
- offset++;
- }
- }
- }
-}
-
-__private_extern__ 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->itemsPtr = (unsigned long *)stackbuffer;
- CFIndex cntx = 0;
- CFIndex used = (CFIndex)ht->bits.used_buckets, cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx];
- for (CFIndex idx = (CFIndex)state->state; 0 < used && idx < cnt && cntx < (CFIndex)count; idx++) {
- CFBasicHashBucket bkt = CFBasicHashGetBucket(ht, idx);
- if (0 < bkt.count) {
- state->itemsPtr[cntx++] = (unsigned long)bkt.weak_key;
- used--;
- }
- state->state++;
- }
- return cntx;
-}
-
-#if ENABLE_MEMORY_COUNTERS
-static volatile int64_t __CFBasicHashTotalCount = 0ULL;
-static volatile int64_t __CFBasicHashTotalSize = 0ULL;
-static volatile int64_t __CFBasicHashPeakCount = 0ULL;
-static volatile int64_t __CFBasicHashPeakSize = 0ULL;
-static volatile int32_t __CFBasicHashSizes[64] = {0};
-#endif
-
-static void __CFBasicHashDrain(CFBasicHashRef ht, Boolean forFinalization) {
-#if ENABLE_MEMORY_COUNTERS
- OSAtomicAdd64Barrier(-1 * (int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
-#endif
-
- CFIndex old_num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
-
- CFAllocatorRef allocator = CFGetAllocator(ht);
- Boolean nullify = (!forFinalization || !CF_IS_COLLECTABLE_ALLOCATOR(allocator));
-
- CFBasicHashValue *old_values = NULL, *old_keys = NULL;
- void *old_counts = NULL;
- uintptr_t *old_hashes = NULL;
-
- old_values = __CFBasicHashGetValues(ht);
- if (nullify) __CFBasicHashSetValues(ht, NULL);
- if (ht->bits.keys_offset) {
- old_keys = __CFBasicHashGetKeys(ht);
- if (nullify) __CFBasicHashSetKeys(ht, NULL);
- }
- if (ht->bits.counts_offset) {
- old_counts = __CFBasicHashGetCounts(ht);
- if (nullify) __CFBasicHashSetCounts(ht, NULL);
- }
- if (__CFBasicHashHasHashCache(ht)) {
- old_hashes = __CFBasicHashGetHashes(ht);
- if (nullify) __CFBasicHashSetHashes(ht, NULL);
- }
-
- if (nullify) {
- ht->bits.mutations++;
- ht->bits.num_buckets_idx = 0;
- ht->bits.used_buckets = 0;
- ht->bits.deleted = 0;
- }
-
- for (CFIndex idx = 0; idx < old_num_buckets; idx++) {
- uintptr_t stack_value = old_values[idx].neutral;
- if (stack_value != 0UL && stack_value != ~0UL) {
- uintptr_t old_value = stack_value;
- if (__CFBasicHashSubABZero == old_value) old_value = 0UL;
- if (__CFBasicHashSubABOne == old_value) old_value = ~0UL;
- __CFBasicHashEjectValue(ht, old_value);
- if (old_keys) {
- uintptr_t old_key = old_keys[idx].neutral;
- if (__CFBasicHashSubABZero == old_key) old_key = 0UL;
- if (__CFBasicHashSubABOne == old_key) old_key = ~0UL;
- __CFBasicHashEjectKey(ht, old_key);
- }
- }
- }
-
- if (forFinalization) {
- ht->callbacks->freeCallbacks(ht, allocator, ht->callbacks);
- }
-
- if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
- CFAllocatorDeallocate(allocator, old_values);
- CFAllocatorDeallocate(allocator, old_keys);
- CFAllocatorDeallocate(allocator, old_counts);
- CFAllocatorDeallocate(allocator, old_hashes);
- }
-
-#if ENABLE_MEMORY_COUNTERS
- int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
- while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
-#endif
-}
-
-static void __CFBasicHashRehash(CFBasicHashRef ht, CFIndex newItemCount) {
-#if ENABLE_MEMORY_COUNTERS
- OSAtomicAdd64Barrier(-1 * (int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
- OSAtomicAdd32Barrier(-1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
-#endif
-
- if (COCOA_HASHTABLE_REHASH_START_ENABLED()) COCOA_HASHTABLE_REHASH_START(ht, CFBasicHashGetNumBuckets(ht), CFBasicHashGetSize(ht, true));
-
- CFIndex new_num_buckets_idx = ht->bits.num_buckets_idx;
- if (0 != newItemCount) {
- if (newItemCount < 0) newItemCount = 0;
- CFIndex new_capacity_req = ht->bits.used_buckets + newItemCount;
- new_num_buckets_idx = __CFBasicHashGetNumBucketsIndexForCapacity(ht, new_capacity_req);
- if (1 == newItemCount && ht->bits.fast_grow) {
- new_num_buckets_idx++;
- }
- }
-
- CFIndex new_num_buckets = __CFBasicHashTableSizes[new_num_buckets_idx];
- CFIndex old_num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
-
- CFBasicHashValue *new_values = NULL, *new_keys = NULL;
- void *new_counts = NULL;
- uintptr_t *new_hashes = NULL;
-
- if (0 < new_num_buckets) {
- new_values = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), CFBasicHashHasStrongValues(ht), __CFBasicHashHasCompactableValues(ht));
- __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));
- __SetLastAllocationEventName(new_keys, "CFBasicHash (key-store)");
- memset(new_keys, 0, new_num_buckets * sizeof(CFBasicHashValue));
- }
- if (ht->bits.counts_offset) {
- new_counts = (uintptr_t *)__CFBasicHashAllocateMemory(ht, new_num_buckets, (1 << ht->bits.counts_width), false, false);
- __SetLastAllocationEventName(new_counts, "CFBasicHash (count-store)");
- memset(new_counts, 0, new_num_buckets * (1 << ht->bits.counts_width));
- }
- if (__CFBasicHashHasHashCache(ht)) {
- new_hashes = (uintptr_t *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(uintptr_t), false, false);
- __SetLastAllocationEventName(new_hashes, "CFBasicHash (hash-store)");
- memset(new_hashes, 0, new_num_buckets * sizeof(uintptr_t));
- }
- }
-
- ht->bits.num_buckets_idx = new_num_buckets_idx;
- ht->bits.deleted = 0;
-
- CFBasicHashValue *old_values = NULL, *old_keys = NULL;
- void *old_counts = NULL;
- uintptr_t *old_hashes = NULL;
-
- old_values = __CFBasicHashGetValues(ht);
- __CFBasicHashSetValues(ht, new_values);
- if (ht->bits.keys_offset) {
- old_keys = __CFBasicHashGetKeys(ht);
- __CFBasicHashSetKeys(ht, new_keys);
- }
- if (ht->bits.counts_offset) {
- old_counts = __CFBasicHashGetCounts(ht);
- __CFBasicHashSetCounts(ht, new_counts);
- }
- if (__CFBasicHashHasHashCache(ht)) {
- old_hashes = __CFBasicHashGetHashes(ht);
- __CFBasicHashSetHashes(ht, new_hashes);
- }
-
- if (0 < old_num_buckets) {
- for (CFIndex idx = 0; idx < old_num_buckets; idx++) {
- uintptr_t stack_value = old_values[idx].neutral;
- if (stack_value != 0UL && stack_value != ~0UL) {
- if (__CFBasicHashSubABZero == stack_value) stack_value = 0UL;
- if (__CFBasicHashSubABOne == stack_value) stack_value = ~0UL;
- uintptr_t stack_key = stack_value;
- if (ht->bits.keys_offset) {
- stack_key = old_keys[idx].neutral;
- if (__CFBasicHashSubABZero == stack_key) stack_key = 0UL;
- if (__CFBasicHashSubABOne == stack_key) stack_key = ~0UL;
- }
- if (ht->bits.indirect_keys) {
- stack_key = ht->callbacks->getIndirectKey(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);
- if (old_keys) {
- __CFBasicHashSetKey(ht, bkt_idx, stack_key, false, false);
- }
- if (old_counts) {
- switch (ht->bits.counts_width) {
- case 0: ((uint8_t *)new_counts)[bkt_idx] = ((uint8_t *)old_counts)[idx]; break;
- case 1: ((uint16_t *)new_counts)[bkt_idx] = ((uint16_t *)old_counts)[idx]; break;
- case 2: ((uint32_t *)new_counts)[bkt_idx] = ((uint32_t *)old_counts)[idx]; break;
- case 3: ((uint64_t *)new_counts)[bkt_idx] = ((uint64_t *)old_counts)[idx]; break;
- }
- }
- if (old_hashes) {
- new_hashes[bkt_idx] = old_hashes[idx];
- }
- }
- }
- }
-
- CFAllocatorRef allocator = CFGetAllocator(ht);
- if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
- CFAllocatorDeallocate(allocator, old_values);
- CFAllocatorDeallocate(allocator, old_keys);
- CFAllocatorDeallocate(allocator, old_counts);
- CFAllocatorDeallocate(allocator, old_hashes);
- }
-
- if (COCOA_HASHTABLE_REHASH_END_ENABLED()) COCOA_HASHTABLE_REHASH_END(ht, CFBasicHashGetNumBuckets(ht), CFBasicHashGetSize(ht, true));
-
-#if ENABLE_MEMORY_COUNTERS
- int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), &__CFBasicHashTotalSize);
- while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
- OSAtomicAdd32Barrier(1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
-#endif
-}
-
-__private_extern__ void CFBasicHashSetCapacity(CFBasicHashRef ht, CFIndex capacity) {
- if (!CFBasicHashIsMutable(ht)) HALT;
- if (ht->bits.used_buckets < capacity) {
- ht->bits.mutations++;
- __CFBasicHashRehash(ht, capacity - ht->bits.used_buckets);
- }
-}
-
-static void __CFBasicHashAddValue(CFBasicHashRef ht, CFIndex bkt_idx, uintptr_t stack_key, uintptr_t stack_value) {
- ht->bits.mutations++;
- if (CFBasicHashGetCapacity(ht) < ht->bits.used_buckets + 1) {
- __CFBasicHashRehash(ht, 1);
- bkt_idx = __CFBasicHashFindBucket_NoCollision(ht, stack_key, 0);
- } else if (__CFBasicHashIsDeleted(ht, bkt_idx)) {
- ht->bits.deleted--;
- }
- uintptr_t key_hash = 0;
- if (__CFBasicHashHasHashCache(ht)) {
- key_hash = __CFBasicHashHashKey(ht, stack_key);
- }
- stack_value = __CFBasicHashImportValue(ht, stack_value);
- if (ht->bits.keys_offset) {
- stack_key = __CFBasicHashImportKey(ht, stack_key);
- }
- __CFBasicHashSetValue(ht, bkt_idx, stack_value, false, false);
- if (ht->bits.keys_offset) {
- __CFBasicHashSetKey(ht, bkt_idx, stack_key, false, false);
- }
- if (ht->bits.counts_offset) {
- __CFBasicHashIncSlotCount(ht, bkt_idx);
- }
- if (__CFBasicHashHasHashCache(ht)) {
- __CFBasicHashGetHashes(ht)[bkt_idx] = key_hash;
- }
- ht->bits.used_buckets++;
-}
-
-static void __CFBasicHashReplaceValue(CFBasicHashRef ht, CFIndex bkt_idx, uintptr_t stack_key, uintptr_t stack_value) {
- ht->bits.mutations++;
- stack_value = __CFBasicHashImportValue(ht, stack_value);
- if (ht->bits.keys_offset) {
- stack_key = __CFBasicHashImportKey(ht, stack_key);
- }
- __CFBasicHashSetValue(ht, bkt_idx, stack_value, false, false);
- if (ht->bits.keys_offset) {
- __CFBasicHashSetKey(ht, bkt_idx, stack_key, false, false);
- }
-}
-
-static void __CFBasicHashRemoveValue(CFBasicHashRef ht, CFIndex bkt_idx) {
- ht->bits.mutations++;
- __CFBasicHashSetValue(ht, bkt_idx, ~0UL, false, true);
- if (ht->bits.keys_offset) {
- __CFBasicHashSetKey(ht, bkt_idx, ~0UL, false, true);
- }
- if (ht->bits.counts_offset) {
- __CFBasicHashDecSlotCount(ht, bkt_idx);
- }
- if (__CFBasicHashHasHashCache(ht)) {
- __CFBasicHashGetHashes(ht)[bkt_idx] = 0;
- }
- ht->bits.used_buckets--;
- ht->bits.deleted++;
- Boolean do_shrink = false;
- if (ht->bits.fast_grow) { // == slow shrink
- do_shrink = (5 < ht->bits.num_buckets_idx && ht->bits.used_buckets < __CFBasicHashGetCapacityForNumBuckets(ht, ht->bits.num_buckets_idx - 5));
- } else {
- do_shrink = (2 < ht->bits.num_buckets_idx && ht->bits.used_buckets < __CFBasicHashGetCapacityForNumBuckets(ht, ht->bits.num_buckets_idx - 2));
- }
- if (do_shrink) {
- __CFBasicHashRehash(ht, -1);
- return;
- }
- do_shrink = (0 == ht->bits.deleted); // .deleted roll-over
- CFIndex num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
- do_shrink = do_shrink || ((20 <= num_buckets) && (num_buckets / 4 <= ht->bits.deleted));
- if (do_shrink) {
- __CFBasicHashRehash(ht, 0);
- }
-}
-
-__private_extern__ 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;
- if (__CFBasicHashSubABZero == stack_value) HALT;
- if (__CFBasicHashSubABOne == stack_value) HALT;
- CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key);
- if (0 < bkt.count) {
- ht->bits.mutations++;
- if (ht->bits.counts_offset && bkt.count < LONG_MAX) { // if not yet as large as a CFIndex can be... otherwise clamp and do nothing
- __CFBasicHashIncSlotCount(ht, bkt.idx);
- return true;
- }
- } else {
- __CFBasicHashAddValue(ht, bkt.idx, stack_key, stack_value);
- return true;
- }
- return false;
-}
-
-__private_extern__ 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;
- if (__CFBasicHashSubABZero == stack_value) HALT;
- if (__CFBasicHashSubABOne == stack_value) HALT;
- CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key);
- if (0 < bkt.count) {
- __CFBasicHashReplaceValue(ht, bkt.idx, stack_key, stack_value);
- }
-}
-
-__private_extern__ 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;
- if (__CFBasicHashSubABZero == stack_value) HALT;
- if (__CFBasicHashSubABOne == stack_value) HALT;
- CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key);
- if (0 < bkt.count) {
- __CFBasicHashReplaceValue(ht, bkt.idx, stack_key, stack_value);
- } else {
- __CFBasicHashAddValue(ht, bkt.idx, stack_key, stack_value);
- }
-}
-
-__private_extern__ 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);
- if (1 < bkt.count) {
- ht->bits.mutations++;
- if (ht->bits.counts_offset && bkt.count < LONG_MAX) { // if not as large as a CFIndex can be... otherwise clamp and do nothing
- __CFBasicHashDecSlotCount(ht, bkt.idx);
- }
- } else if (0 < bkt.count) {
- __CFBasicHashRemoveValue(ht, bkt.idx);
- }
- return bkt.count;
-}
-
-__private_extern__ CFIndex CFBasicHashRemoveValueAtIndex(CFBasicHashRef ht, CFIndex idx) {
- if (!CFBasicHashIsMutable(ht)) HALT;
- CFBasicHashBucket bkt = CFBasicHashGetBucket(ht, idx);
- if (1 < bkt.count) {
- ht->bits.mutations++;
- if (ht->bits.counts_offset && bkt.count < LONG_MAX) { // if not as large as a CFIndex can be... otherwise clamp and do nothing
- __CFBasicHashDecSlotCount(ht, bkt.idx);
- }
- } else if (0 < bkt.count) {
- __CFBasicHashRemoveValue(ht, bkt.idx);
- }
- return bkt.count;
-}
-
-__private_extern__ 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) {
- if (!CFBasicHashIsMutable(ht)) HALT;
- if (__CFBasicHashSubABZero == stack_key) HALT;
- if (__CFBasicHashSubABOne == stack_key) HALT;
- if (__CFBasicHashSubABZero == int_value) HALT;
- if (__CFBasicHashSubABOne == int_value) HALT;
- CFBasicHashBucket bkt = __CFBasicHashFindBucket(ht, stack_key);
- if (0 < bkt.count) {
- ht->bits.mutations++;
- } else {
- // must rehash before renumbering
- if (CFBasicHashGetCapacity(ht) < ht->bits.used_buckets + 1) {
- __CFBasicHashRehash(ht, 1);
- bkt.idx = __CFBasicHashFindBucket_NoCollision(ht, stack_key, 0);
- }
- CFIndex cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx];
- for (CFIndex idx = 0; idx < cnt; idx++) {
- if (!__CFBasicHashIsEmptyOrDeleted(ht, idx)) {
- uintptr_t stack_value = __CFBasicHashGetValue(ht, idx);
- if (int_value <= stack_value) {
- stack_value++;
- __CFBasicHashSetValue(ht, idx, stack_value, true, false);
- ht->bits.mutations++;
- }
- }
- }
- __CFBasicHashAddValue(ht, bkt.idx, stack_key, int_value);
- return true;
- }
- return false;
-}
-
-void CFBasicHashRemoveIntValueAndDec(CFBasicHashRef ht, uintptr_t int_value) {
- if (!CFBasicHashIsMutable(ht)) HALT;
- if (__CFBasicHashSubABZero == int_value) HALT;
- if (__CFBasicHashSubABOne == int_value) HALT;
- uintptr_t bkt_idx = ~0UL;
- CFIndex cnt = (CFIndex)__CFBasicHashTableSizes[ht->bits.num_buckets_idx];
- for (CFIndex idx = 0; idx < cnt; idx++) {
- if (!__CFBasicHashIsEmptyOrDeleted(ht, idx)) {
- uintptr_t stack_value = __CFBasicHashGetValue(ht, idx);
- if (int_value == stack_value) {
- bkt_idx = idx;
- }
- if (int_value < stack_value) {
- stack_value--;
- __CFBasicHashSetValue(ht, idx, stack_value, true, false);
- ht->bits.mutations++;
- }
- }
- }
- __CFBasicHashRemoveValue(ht, bkt_idx);
-}
-
-__private_extern__ 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 *);
- if (__CFBasicHashHasHashCache(ht)) size += sizeof(uintptr_t *);
- if (total) {
- CFIndex num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
- if (0 < num_buckets) {
- size += malloc_size(__CFBasicHashGetValues(ht));
- 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) {
- 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("%@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("%@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);
- CFBasicHashApply(ht, ^(CFBasicHashBucket bkt) {
- CFStringRef vDesc = NULL, kDesc = NULL;
- if (!describeElements) {
- vDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)bkt.weak_value);
- if (ht->bits.keys_offset) {
- kDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)bkt.weak_key);
- }
- } else {
- vDesc = ht->callbacks->copyValueDescription(ht, bkt.weak_value);
- if (ht->bits.keys_offset) {
- kDesc = ht->callbacks->copyKeyDescription(ht, bkt.weak_key);
- }
- }
- if (ht->bits.keys_offset && ht->bits.counts_offset) {
- CFStringAppendFormat(result, NULL, CFSTR("%@%ld : %@ = %@ (%ld)\n"), entryPrefix, bkt.idx, kDesc, vDesc, bkt.count);
- } else if (ht->bits.keys_offset) {
- CFStringAppendFormat(result, NULL, CFSTR("%@%ld : %@ = %@\n"), entryPrefix, bkt.idx, kDesc, vDesc);
- } else if (ht->bits.counts_offset) {
- CFStringAppendFormat(result, NULL, CFSTR("%@%ld : %@ (%ld)\n"), entryPrefix, bkt.idx, vDesc, bkt.count);
- } else {
- CFStringAppendFormat(result, NULL, CFSTR("%@%ld : %@\n"), entryPrefix, bkt.idx, vDesc);
- }
- if (kDesc) CFRelease(kDesc);
- if (vDesc) CFRelease(vDesc);
- return (Boolean)true;
- });
- CFStringAppendFormat(result, NULL, CFSTR("%@}\n"), prefix);
- return result;
-}
-
-__private_extern__ 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) {
- 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) {
- CFBasicHashRef ht = (CFBasicHashRef)cf;
- return CFBasicHashGetCount(ht);
-}
-
-__private_extern__ CFStringRef __CFBasicHashCopyDescription(CFTypeRef cf) {
- CFBasicHashRef ht = (CFBasicHashRef)cf;
- CFStringRef desc = CFBasicHashCopyDescription(ht, false, CFSTR(""), CFSTR("\t"), true);
- CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFBasicHash %p [%p]>%@"), cf, CFGetAllocator(cf), desc);
- CFRelease(desc);
- return result;
-}
-
-__private_extern__ void __CFBasicHashDeallocate(CFTypeRef cf) {
- CFBasicHashRef ht = (CFBasicHashRef)cf;
- if (ht->bits.finalized) HALT;
- ht->bits.finalized = 1;
- __CFBasicHashDrain(ht, true);
-#if ENABLE_MEMORY_COUNTERS
- OSAtomicAdd64Barrier(-1, &__CFBasicHashTotalCount);
- OSAtomicAdd32Barrier(-1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
-#endif
-}
-
-static CFTypeID __kCFBasicHashTypeID = _kCFRuntimeNotATypeID;
-
-static const CFRuntimeClass __CFBasicHashClass = {
- _kCFRuntimeScannedObject,
- "CFBasicHash",
- NULL, // init
- NULL, // copy
- __CFBasicHashDeallocate,
- __CFBasicHashEqual,
- __CFBasicHashHash,
- NULL, //
- __CFBasicHashCopyDescription
-};
-
-__private_extern__ CFTypeID CFBasicHashGetTypeID(void) {
- if (_kCFRuntimeNotATypeID == __kCFBasicHashTypeID) __kCFBasicHashTypeID = _CFRuntimeRegisterClass(&__CFBasicHashClass);
- return __kCFBasicHashTypeID;
-}
-
-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
- if (flags & kCFBasicHashHasHashCache) size += sizeof(uintptr_t *); // hashes
- CFBasicHashRef ht = (CFBasicHashRef)_CFRuntimeCreateInstance(allocator, CFBasicHashGetTypeID(), size, NULL);
- if (NULL == ht) HALT;
-
- ht->bits.finalized = 0;
- ht->bits.hash_style = (flags >> 13) & 0x3;
- ht->bits.fast_grow = (flags & kCFBasicHashAggressiveGrowth) ? 1 : 0;
- ht->bits.counts_width = 0;
- ht->bits.strong_values = (flags & kCFBasicHashStrongValues) ? 1 : 0;
- ht->bits.strong_keys = (flags & kCFBasicHashStrongKeys) ? 1 : 0;
- ht->bits.weak_values = (flags & kCFBasicHashWeakValues) ? 1 : 0;
- ht->bits.weak_keys = (flags & kCFBasicHashWeakKeys) ? 1 : 0;
- 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;
- ht->bits.mutations = 1;
-
- if (ht->bits.strong_values && ht->bits.weak_values) HALT;
- if (ht->bits.strong_values && ht->bits.int_values) HALT;
- if (ht->bits.strong_keys && ht->bits.weak_keys) HALT;
- if (ht->bits.strong_keys && ht->bits.int_keys) HALT;
- if (ht->bits.weak_values && ht->bits.int_values) HALT;
- if (ht->bits.weak_keys && ht->bits.int_keys) HALT;
- if (ht->bits.indirect_keys && ht->bits.strong_keys) HALT;
- if (ht->bits.indirect_keys && ht->bits.weak_keys) HALT;
- if (ht->bits.indirect_keys && ht->bits.int_keys) HALT;
-
- uint64_t offset = 1;
- ht->bits.keys_offset = (flags & kCFBasicHashHasKeys) ? offset++ : 0;
- ht->bits.counts_offset = (flags & kCFBasicHashHasCounts) ? offset++ : 0;
- ht->bits.hashes_offset = (flags & kCFBasicHashHasHashCache) ? offset++ : 0;
-
-#if defined(__arm__)
- ht->bits.hashes_offset = 0;
- ht->bits.strong_values = 0;
- ht->bits.strong_keys = 0;
- ht->bits.weak_values = 0;
- ht->bits.weak_keys = 0;
-#endif
-
- __AssignWithWriteBarrier(&ht->callbacks, cb);
- for (CFIndex idx = 0; idx < offset; idx++) {
- ht->pointers[idx] = NULL;
- }
-
-#if ENABLE_MEMORY_COUNTERS
- int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
- while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
- int64_t count_now = OSAtomicAdd64Barrier(1, & __CFBasicHashTotalCount);
- while (__CFBasicHashPeakCount < count_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakCount, count_now, & __CFBasicHashPeakCount));
- OSAtomicAdd32Barrier(1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
-#endif
-
- return ht;
-}
-
-CFBasicHashRef CFBasicHashCreateCopy(CFAllocatorRef allocator, CFConstBasicHashRef src_ht) {
- size_t size = CFBasicHashGetSize(src_ht, false) - sizeof(CFRuntimeBase);
- CFBasicHashRef ht = (CFBasicHashRef)_CFRuntimeCreateInstance(allocator, CFBasicHashGetTypeID(), size, NULL);
- if (NULL == ht) HALT;
-
- memmove((uint8_t *)ht + sizeof(CFRuntimeBase), (uint8_t *)src_ht + sizeof(CFRuntimeBase), sizeof(ht->bits));
- if (kCFUseCollectableAllocator && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
- ht->bits.strong_values = 0;
- ht->bits.strong_keys = 0;
- ht->bits.weak_values = 0;
- ht->bits.weak_keys = 0;
- }
- ht->bits.finalized = 0;
- ht->bits.mutations = 1;
- CFBasicHashCallbacks *newcb = src_ht->callbacks->copyCallbacks(src_ht, allocator, src_ht->callbacks);
- if (NULL == newcb) HALT;
- __AssignWithWriteBarrier(&ht->callbacks, newcb);
-
- CFIndex new_num_buckets = __CFBasicHashTableSizes[ht->bits.num_buckets_idx];
- if (0 == new_num_buckets) {
-#if ENABLE_MEMORY_COUNTERS
- int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
- while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
- int64_t count_now = OSAtomicAdd64Barrier(1, & __CFBasicHashTotalCount);
- while (__CFBasicHashPeakCount < count_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakCount, count_now, & __CFBasicHashPeakCount));
- OSAtomicAdd32Barrier(1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
-#endif
- return ht;
- }
-
- CFBasicHashValue *new_values = NULL, *new_keys = NULL;
- void *new_counts = NULL;
- uintptr_t *new_hashes = NULL;
-
- if (0 < new_num_buckets) {
- new_values = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), CFBasicHashHasStrongValues(ht), __CFBasicHashHasCompactableValues(ht));
- __SetLastAllocationEventName(new_values, "CFBasicHash (value-store)");
- if (ht->bits.keys_offset) {
- new_keys = (CFBasicHashValue *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(CFBasicHashValue), CFBasicHashHasStrongKeys(ht), false);
- __SetLastAllocationEventName(new_keys, "CFBasicHash (key-store)");
- }
- if (ht->bits.counts_offset) {
- new_counts = (uintptr_t *)__CFBasicHashAllocateMemory(ht, new_num_buckets, (1 << ht->bits.counts_width), false, false);
- __SetLastAllocationEventName(new_counts, "CFBasicHash (count-store)");
- }
- if (__CFBasicHashHasHashCache(ht)) {
- new_hashes = (uintptr_t *)__CFBasicHashAllocateMemory(ht, new_num_buckets, sizeof(uintptr_t), false, false);
- __SetLastAllocationEventName(new_hashes, "CFBasicHash (hash-store)");
- }
- }
-
- CFBasicHashValue *old_values = NULL, *old_keys = NULL;
- void *old_counts = NULL;
- uintptr_t *old_hashes = NULL;
-
- old_values = __CFBasicHashGetValues(src_ht);
- if (src_ht->bits.keys_offset) {
- old_keys = __CFBasicHashGetKeys(src_ht);
- }
- if (src_ht->bits.counts_offset) {
- old_counts = __CFBasicHashGetCounts(src_ht);
- }
- if (__CFBasicHashHasHashCache(src_ht)) {
- old_hashes = __CFBasicHashGetHashes(src_ht);
- }
-
- __CFBasicHashSetValues(ht, new_values);
- if (new_keys) {
- __CFBasicHashSetKeys(ht, new_keys);
- }
- if (new_counts) {
- __CFBasicHashSetCounts(ht, new_counts);
- }
- if (new_hashes) {
- __CFBasicHashSetHashes(ht, new_hashes);
- }
-
- for (CFIndex idx = 0; idx < new_num_buckets; idx++) {
- uintptr_t stack_value = old_values[idx].neutral;
- if (stack_value != 0UL && stack_value != ~0UL) {
- uintptr_t old_value = stack_value;
- if (__CFBasicHashSubABZero == old_value) old_value = 0UL;
- if (__CFBasicHashSubABOne == old_value) old_value = ~0UL;
- __CFBasicHashSetValue(ht, idx, __CFBasicHashImportValue(ht, old_value), true, false);
- if (new_keys) {
- uintptr_t old_key = old_keys[idx].neutral;
- if (__CFBasicHashSubABZero == old_key) old_key = 0UL;
- if (__CFBasicHashSubABOne == old_key) old_key = ~0UL;
- __CFBasicHashSetKey(ht, idx, __CFBasicHashImportKey(ht, old_key), true, false);
- }
- } else {
- __CFBasicHashSetValue(ht, idx, stack_value, true, true);
- if (new_keys) {
- __CFBasicHashSetKey(ht, idx, stack_value, true, true);
- }
- }
- }
- if (new_counts) memmove(new_counts, old_counts, new_num_buckets * (1 << ht->bits.counts_width));
- if (new_hashes) memmove(new_hashes, old_hashes, new_num_buckets * sizeof(uintptr_t));
-
-#if ENABLE_MEMORY_COUNTERS
- int64_t size_now = OSAtomicAdd64Barrier((int64_t) CFBasicHashGetSize(ht, true), & __CFBasicHashTotalSize);
- while (__CFBasicHashPeakSize < size_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakSize, size_now, & __CFBasicHashPeakSize));
- int64_t count_now = OSAtomicAdd64Barrier(1, & __CFBasicHashTotalCount);
- while (__CFBasicHashPeakCount < count_now && !OSAtomicCompareAndSwap64Barrier(__CFBasicHashPeakCount, count_now, & __CFBasicHashPeakCount));
- OSAtomicAdd32Barrier(1, &__CFBasicHashSizes[ht->bits.num_buckets_idx]);
-#endif
-
- 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;
-}
-
*/
/* CFBasicHashFindBucket.m
- Copyright (c) 2009-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2009-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
--- /dev/null
+/*
+ * Copyright (c) 2012 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@
+ */
+
+/* CFBigNumber.c
+ Copyright (c) 2012-2012, Apple Inc. All rights reserved.
+ Responsibility: Christopher Kane
+ Original author: Zhi Feng Huang
+*/
+
+#include <CoreFoundation/CFBigNumber.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "CFInternal.h"
+
+
+#define kCFNumberSInt128Type 17
+
+#if __LP64__
+
+#ifndef _INT128_T
+#define _INT128_T
+typedef __int128_t int128_t;
+#endif
+
+#ifndef _UINT128_T
+#define _UINT128_T
+typedef __uint128_t uint128_t;
+#endif
+
+#ifndef INT128_MIN
+#define INT128_MIN ((__int128_t)0 - ((__int128_t)1 << 126) - ((__int128_t)1 << 126))
+#endif
+
+#ifndef INT128_MAX
+#define INT128_MAX ((__int128_t)-1 + ((__int128_t)1 << 126) + ((__int128_t)1 << 126))
+#endif
+
+#ifndef UINT128_MAX
+#define UINT128_MAX (((__uint128_t)1 << 127) - (__uint128_t)1 + ((__uint128_t)1 << 127))
+#endif
+
+#endif
+
+
+#define BIG_DIGITS_LIMIT 1000000000L
+#define BIG_DIGITS_LIMIT_2 ((uint64_t)BIG_DIGITS_LIMIT * (uint64_t)BIG_DIGITS_LIMIT)
+#define BIG_DIGITS_LIMIT_3 ((__uint128_t)BIG_DIGITS_LIMIT_2 * (__uint128_t)BIG_DIGITS_LIMIT)
+#define BIG_DIGITS_LIMIT_4 ((__uint128_t)BIG_DIGITS_LIMIT_3 * (__uint128_t)BIG_DIGITS_LIMIT)
+
+#define GET_FIFTH_DIGIT(A) (A / BIG_DIGITS_LIMIT_4)
+#define GET_FOURTH_DIGIT(A) (A / BIG_DIGITS_LIMIT_3)
+#define GET_THIRD_DIGIT(A) (A / BIG_DIGITS_LIMIT_2)
+#define GET_SECOND_DIGIT(A) (A / BIG_DIGITS_LIMIT)
+
+#define GET_REMAINDER_FIFTH_DIGIT(A,B) (A - B * BIG_DIGITS_LIMIT_4)
+#define GET_REMAINDER_FOURTH_DIGIT(A,B) (A - B * BIG_DIGITS_LIMIT_3)
+#define GET_REMAINDER_THIRD_DIGIT(A,B) (A - B * BIG_DIGITS_LIMIT_2)
+#define GET_REMAINDER_SECOND_DIGIT(A,B) (A - B * BIG_DIGITS_LIMIT)
+
+
+void _CFBigNumInitWithInt8(_CFBigNum *r, int8_t inNum) {
+ memset(r, 0, sizeof(*r));
+ uint8_t unsignInNum = inNum;
+ if (inNum < 0) {
+ r->sign = -1;
+ unsignInNum = -1 * inNum;
+ }
+ r->digits[0] = unsignInNum;
+}
+
+void _CFBigNumInitWithInt16(_CFBigNum *r, int16_t inNum) {
+ memset(r, 0, sizeof(*r));
+ uint16_t unsignInNum = inNum;
+ if (inNum < 0) {
+ r->sign = -1;
+ unsignInNum = -1 * inNum;
+ }
+ r->digits[0] = unsignInNum;
+}
+
+void _CFBigNumInitWithInt32(_CFBigNum *r, int32_t inNum) {
+ memset(r, 0, sizeof(*r));
+ uint32_t unsignInNum = inNum;
+ if (inNum < 0) {
+ r->sign = -1;
+ unsignInNum = -1 * inNum;
+ }
+ uint32_t dig0 = GET_SECOND_DIGIT(unsignInNum);
+ r->digits[0] = GET_REMAINDER_SECOND_DIGIT(unsignInNum, dig0);
+ r->digits[1] = dig0;
+}
+
+void _CFBigNumInitWithInt64(_CFBigNum *r, int64_t inNum) {
+ memset(r, 0, sizeof(*r));
+ uint64_t unsignInNum = inNum;
+ if (inNum < 0) {
+ r->sign = -1;
+ unsignInNum = -1 * inNum;
+ }
+ uint32_t dig2 = GET_THIRD_DIGIT(unsignInNum);
+ unsignInNum = GET_REMAINDER_THIRD_DIGIT(unsignInNum, (uint64_t)dig2);
+ uint32_t dig1 = GET_SECOND_DIGIT(unsignInNum);
+ r->digits[0] = GET_REMAINDER_SECOND_DIGIT(unsignInNum, (uint64_t)dig1);
+ r->digits[1] = dig1;
+ r->digits[2] = dig2;
+}
+
+#ifdef __LP64__
+void _CFBigNumInitWithInt128(_CFBigNum *r, __int128_t inNum) {
+ memset(r, 0, sizeof(*r));
+ __uint128_t unsignInNum = inNum;
+ if (inNum < 0) {
+ r->sign = -1;
+ unsignInNum = -1 * inNum;
+ }
+ uint32_t dig4 = GET_FIFTH_DIGIT(unsignInNum);
+ unsignInNum = GET_REMAINDER_FIFTH_DIGIT(unsignInNum, (__uint128_t)dig4);
+ uint32_t dig3 = GET_FOURTH_DIGIT(unsignInNum);
+ unsignInNum = GET_REMAINDER_FOURTH_DIGIT(unsignInNum, (__uint128_t)dig3);
+ uint32_t dig2 = GET_THIRD_DIGIT(unsignInNum);
+ unsignInNum = GET_REMAINDER_THIRD_DIGIT(unsignInNum, (__uint128_t)dig2);
+ uint32_t dig1 = GET_SECOND_DIGIT(unsignInNum);
+ r->digits[0] = GET_REMAINDER_SECOND_DIGIT(unsignInNum, (__uint128_t)dig1);
+ r->digits[1] = dig1;
+ r->digits[2] = dig2;
+ r->digits[3] = dig3;
+ r->digits[4] = dig4;
+}
+#endif
+
+void _CFBigNumInitWithUInt8(_CFBigNum *r, uint8_t inNum) {
+ memset(r, 0, sizeof(*r));
+ uint8_t unsignInNum = inNum;
+ r->digits[0] = unsignInNum;
+}
+
+void _CFBigNumInitWithUInt16(_CFBigNum *r, uint16_t inNum) {
+ memset(r, 0, sizeof(*r));
+ uint16_t unsignInNum = inNum;
+ r->digits[0] = unsignInNum;
+}
+
+void _CFBigNumInitWithUInt32(_CFBigNum *r, uint32_t inNum) {
+ memset(r, 0, sizeof(*r));
+ uint32_t unsignInNum = inNum;
+ uint32_t dig0 = GET_SECOND_DIGIT(unsignInNum);
+ r->digits[0] = GET_REMAINDER_SECOND_DIGIT(unsignInNum, dig0);
+ r->digits[1] = dig0;
+}
+
+void _CFBigNumInitWithUInt64(_CFBigNum *r, uint64_t inNum) {
+ memset(r, 0, sizeof(*r));
+ uint64_t unsignInNum = inNum;
+ uint32_t dig2 = GET_THIRD_DIGIT(unsignInNum);
+ unsignInNum = GET_REMAINDER_THIRD_DIGIT(unsignInNum, (uint64_t)dig2);
+ uint32_t dig1 = GET_SECOND_DIGIT(unsignInNum);
+ r->digits[0] = GET_REMAINDER_SECOND_DIGIT(unsignInNum, (uint64_t)dig1);
+ r->digits[1] = dig1;
+ r->digits[2] = dig2;
+}
+
+#ifdef __LP64__
+void _CFBigNumInitWithUInt128(_CFBigNum *r, __uint128_t inNum) {
+ memset(r, 0, sizeof(*r));
+ __uint128_t unsignInNum = inNum;
+ uint32_t dig4 = GET_FIFTH_DIGIT(unsignInNum);
+ unsignInNum = GET_REMAINDER_FIFTH_DIGIT(unsignInNum, (__uint128_t)dig4);
+ uint32_t dig3 = GET_FOURTH_DIGIT(unsignInNum);
+ unsignInNum = GET_REMAINDER_FOURTH_DIGIT(unsignInNum, (__uint128_t)dig3);
+ uint32_t dig2 = GET_THIRD_DIGIT(unsignInNum);
+ unsignInNum = GET_REMAINDER_THIRD_DIGIT(unsignInNum, (__uint128_t)dig2);
+ uint32_t dig1 = GET_SECOND_DIGIT(unsignInNum);
+ r->digits[0] = GET_REMAINDER_SECOND_DIGIT(unsignInNum, (__uint128_t)dig1);
+ r->digits[1] = dig1;
+ r->digits[2] = dig2;
+ r->digits[3] = dig3;
+ r->digits[4] = dig4;
+}
+#endif
+
+
+int8_t _CFBigNumGetInt8(const _CFBigNum *num) {
+ int8_t result = num->digits[0];
+ if (num->sign < 0) {
+ result = -1 * result;
+ }
+ return result;
+}
+
+int16_t _CFBigNumGetInt16(const _CFBigNum *num) {
+ int16_t result = num->digits[0];
+ if (num->sign < 0) {
+ result = -1 * result;
+ }
+ return result;
+}
+
+int32_t _CFBigNumGetInt32(const _CFBigNum *num) {
+ int32_t result = num->digits[0];
+ result += num->digits[1] * BIG_DIGITS_LIMIT;
+ if (num->sign < 0) {
+ result = -1 * result;
+ }
+ return result;
+}
+
+int64_t _CFBigNumGetInt64(const _CFBigNum *num) {
+ int64_t result = num->digits[0];
+ result += (int64_t)num->digits[1] * BIG_DIGITS_LIMIT;
+ result += (int64_t)num->digits[2] * BIG_DIGITS_LIMIT_2;
+ if (num->sign < 0) {
+ result = -1 * result;
+ }
+ return result;
+}
+
+#if __LP64__
+__int128_t _CFBigNumGetInt128(const _CFBigNum *num) {
+ __int128_t result = num->digits[0];
+ result += (__int128_t)num->digits[1] * BIG_DIGITS_LIMIT;
+ result += (__int128_t)num->digits[2] * BIG_DIGITS_LIMIT_2;
+ result += (__int128_t)num->digits[3] * BIG_DIGITS_LIMIT_3;
+ result += (__int128_t)num->digits[4] * BIG_DIGITS_LIMIT_4;
+ if (num->sign < 0) {
+ result = -1 * result;
+ }
+ return result;
+}
+#endif
+
+uint8_t _CFBigNumGetUInt8(const _CFBigNum *num) {
+ uint8_t result = num->digits[0];
+ return result;
+}
+
+uint16_t _CFBigNumGetUInt16(const _CFBigNum *num) {
+ uint16_t result = num->digits[0];
+ return result;
+}
+
+uint32_t _CFBigNumGetUInt32(const _CFBigNum *num) {
+ uint32_t result = num->digits[0];
+ result += num->digits[1] * BIG_DIGITS_LIMIT;
+ return result;
+}
+
+uint64_t _CFBigNumGetUInt64(const _CFBigNum *num) {
+ uint64_t result = num->digits[0];
+ result += (uint64_t)num->digits[1] * BIG_DIGITS_LIMIT;
+ result += (uint64_t)num->digits[2] * BIG_DIGITS_LIMIT_2;
+ return result;
+}
+
+#if __LP64__
+__uint128_t _CFBigNumGetUInt128(const _CFBigNum *num) {
+ __uint128_t result = num->digits[0];
+ result += (__uint128_t)num->digits[1] * BIG_DIGITS_LIMIT;
+ result += (__uint128_t)num->digits[2] * BIG_DIGITS_LIMIT_2;
+ result += (__uint128_t)num->digits[3] * BIG_DIGITS_LIMIT_3;
+ result += (__uint128_t)num->digits[4] * BIG_DIGITS_LIMIT_4;
+ return result;
+}
+#endif
+
+
+void _CFBigNumInitWithCFNumber(_CFBigNum *r, CFNumberRef inNum) {
+ uint8_t bytes[128];
+ memset(bytes, 0, sizeof(bytes));
+ CFNumberType type = CFNumberGetType(inNum);
+ CFNumberGetValue(inNum, type, (void *)bytes);
+ _CFBigNumInitWithBytes(r, (const void *)bytes, type);
+}
+
+void _CFBigNumInitWithBytes(_CFBigNum *r, const void *bytes, CFNumberType type) {
+ switch (type) {
+ case kCFNumberSInt8Type:
+ _CFBigNumInitWithInt8(r, *(int8_t *)bytes);
+ return;
+ case kCFNumberSInt16Type:
+ _CFBigNumInitWithInt16(r, *(int16_t *)bytes);
+ return;
+ case kCFNumberSInt32Type:
+ _CFBigNumInitWithInt32(r, *(int32_t *)bytes);
+ return;
+ case kCFNumberSInt64Type:
+ _CFBigNumInitWithInt64(r, *(int64_t *)bytes);
+ return;
+ case kCFNumberCharType:
+ _CFBigNumInitWithInt8(r, *(int8_t *)bytes);
+ return;
+ case kCFNumberShortType:
+ _CFBigNumInitWithInt16(r, *(int16_t *)bytes);
+ return;
+ case kCFNumberIntType:
+ _CFBigNumInitWithInt32(r, *(int32_t *)bytes);
+ return;
+ case kCFNumberLongType:
+ if (sizeof(long) == 8) {
+ _CFBigNumInitWithInt64(r, *(int64_t *)bytes);
+ } else {
+ _CFBigNumInitWithInt32(r, *(int32_t *)bytes);
+ }
+ return;
+ case kCFNumberLongLongType:
+ _CFBigNumInitWithInt64(r, *(int64_t *)bytes);
+ return;
+ case kCFNumberCFIndexType:
+ if (sizeof(CFIndex) == 8) {
+ _CFBigNumInitWithInt64(r, *(int64_t *)bytes);
+ } else {
+ _CFBigNumInitWithInt32(r, *(int32_t *)bytes);
+ }
+ return;
+ case kCFNumberNSIntegerType:
+ if (sizeof(long) == 8) { // NSInteger follows long
+ _CFBigNumInitWithInt64(r, *(int64_t *)bytes);
+ } else {
+ _CFBigNumInitWithInt32(r, *(int32_t *)bytes);
+ }
+ return;
+#if __LP64__
+ case kCFNumberSInt128Type:
+ _CFBigNumInitWithInt128(r, *(__int128_t *)bytes);
+ return;
+#endif
+ default:
+ return;
+ }
+}
+
+CFNumberRef _CFNumberCreateWithBigNum(const _CFBigNum *input) {
+ if (0 == input->digits[4] && 0 == input->digits[3] && 0 == input->digits[2] && 0 == input->digits[1]) {
+ // This bumps up the size of the most negative n-bit value to the next larger size; oh well
+ if (input->digits[0] <= INT8_MAX) {
+ int8_t num = _CFBigNumGetInt8(input);
+ CFNumberRef result = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt8Type, (const void *)&num);
+ return result;
+ } else if (input->digits[0] <= INT16_MAX) {
+ int16_t num = _CFBigNumGetInt16(input);
+ CFNumberRef result = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt16Type, (const void *)&num);
+ return result;
+ }
+ }
+ _CFBigNum maxlimit, minlimit;
+ if (0 == input->digits[4] && 0 == input->digits[3] && 0 == input->digits[2]) {
+ _CFBigNumInitWithInt32(&maxlimit, INT32_MAX);
+ _CFBigNumInitWithInt32(&minlimit, INT32_MIN);
+ CFComparisonResult cr = _CFBigNumCompare(input, &maxlimit);
+ CFComparisonResult crn = _CFBigNumCompare(input, &minlimit);
+ if ((kCFCompareLessThan == cr || kCFCompareEqualTo == cr) && (kCFCompareLessThan != crn)) {
+ int32_t num = _CFBigNumGetInt32(input);
+ CFNumberRef result = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt32Type, (const void *)&num);
+ return result;
+ }
+ }
+ if (0 == input->digits[4] && 0 == input->digits[3]) {
+ _CFBigNumInitWithInt64(&maxlimit, INT64_MAX);
+ _CFBigNumInitWithInt64(&minlimit, INT64_MIN);
+ CFComparisonResult cr = _CFBigNumCompare(input, &maxlimit);
+ CFComparisonResult crn = _CFBigNumCompare(input, &minlimit);
+ if ((kCFCompareLessThan == cr || kCFCompareEqualTo == cr) && (kCFCompareLessThan != crn)) {
+ int64_t num = _CFBigNumGetInt64(input);
+ CFNumberRef result = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt64Type, (const void *)&num);
+ return result;
+ }
+ }
+#if __LP64__
+ _CFBigNumInitWithInt128(&maxlimit, INT128_MAX);
+ _CFBigNumInitWithInt128(&minlimit, INT128_MIN);
+ CFComparisonResult cr = _CFBigNumCompare(input, &maxlimit);
+ CFComparisonResult crn = _CFBigNumCompare(input, &minlimit);
+ if ((kCFCompareLessThan == cr || kCFCompareEqualTo == cr) && (kCFCompareLessThan != crn)) {
+ __int128_t num = _CFBigNumGetInt128(input);
+ CFNumberRef result = CFNumberCreate(kCFAllocatorSystemDefault, kCFNumberSInt128Type, (const void *)&num);
+ return result;
+ }
+#endif
+ return NULL;
+}
+
+CFComparisonResult _CFBigNumCompare(const _CFBigNum *a, const _CFBigNum *b) {
+ Boolean sameSign = a->sign == b->sign;
+ if (sameSign) {
+ Boolean negative = a->sign < 0;
+ for (CFIndex i = sizeof(a->digits) / sizeof(a->digits[0]); i--;) {
+ if (a->digits[i] < b->digits[i]) {
+ return !negative ? kCFCompareLessThan : kCFCompareGreaterThan;
+ }
+ if (a->digits[i] > b->digits[i]) {
+ return negative ? kCFCompareLessThan : kCFCompareGreaterThan;
+ }
+ }
+ return kCFCompareEqualTo;
+ }
+ return (a->sign < b->sign) ? kCFCompareLessThan : kCFCompareGreaterThan;
+}
+
+// abs(a) < abs(b)
+// do not care about the sign
+static Boolean _CFBigNumAbsoluteLessThan(const _CFBigNum *a, const _CFBigNum *b) {
+ for (CFIndex i = sizeof(a->digits) / sizeof(a->digits[0]); i--;) {
+ if (a->digits[i] < b->digits[i]) {
+ return true;
+ }
+ if (a->digits[i] > b->digits[i]) {
+ return false;
+ }
+ }
+ return false;
+}
+
+// r = a * -1
+void _CFBigNumNeg(_CFBigNum *r, const _CFBigNum *a) {
+ memmove(r, a, sizeof(*a));
+ Boolean aIsZero = true;
+ for (CFIndex i = 0; i < sizeof(a->digits) / sizeof(a->digits[0]); i++) {
+ if (a->digits[i] != 0) {
+ aIsZero = false;
+ break;
+ }
+ }
+ // if a is zero, we do not flip the sign
+ if (!aIsZero) {
+ // 0 -> -1
+ // -1 -> 0
+ r->sign = r->sign * r->sign - 1;
+ }
+}
+
+uint8_t _CFBigNumAdd(_CFBigNum *r, const _CFBigNum *a, const _CFBigNum *b) {
+ uint8_t carry = 0;
+ Boolean sameSign = a->sign == b->sign;
+ if (sameSign) {
+ for (CFIndex i = 0; i < sizeof(a->digits) / sizeof(a->digits[0]); i++) {
+ uint32_t result = a->digits[i] + b->digits[i] + carry;
+ if (result > BIG_DIGITS_LIMIT) {
+ carry = 1;
+ result -= BIG_DIGITS_LIMIT;
+ } else {
+ carry = 0;
+ }
+ r->digits[i] = result;
+ }
+ r->sign = a->sign;
+ return carry;
+ } else {
+ // the algorithm here is to find the larger one and do the subtraction and then neg the result if necessary
+ const _CFBigNum *bigNum = NULL;
+ const _CFBigNum *smallNum = NULL;
+ if (_CFBigNumAbsoluteLessThan(a, b)) {
+ bigNum = b;
+ smallNum = a;
+ } else {
+ bigNum = a;
+ smallNum = b;
+ }
+ for (int i = 0; i < sizeof(a->digits) / sizeof(a->digits[0]); i++) {
+ int64_t result = (int64_t)bigNum->digits[i] - (int64_t)smallNum->digits[i] - carry;
+ if (result < 0) {
+ carry = 1;
+ result += BIG_DIGITS_LIMIT;
+ } else {
+ carry = 0;
+ }
+ r->digits[i] = result;
+ }
+ if (bigNum->sign < 0) {
+ r->sign = -1;
+ } else {
+ r->sign = 0;
+ }
+ return carry;
+ }
+}
+
+uint8_t _CFBigNumSub(_CFBigNum *r, const _CFBigNum *a, const _CFBigNum *b) {
+ _CFBigNum nb;
+ _CFBigNumNeg(&nb, b);
+ return _CFBigNumAdd(r, a, &nb);
+}
+
+
+void _CFBigNumToCString(const _CFBigNum *vp, Boolean leading_zeros, Boolean leading_plus, char *buffer, size_t buflen) {
+ if (vp->sign < 0) {
+ *buffer++ = '-';
+ buflen--;
+ } else if (leading_plus) {
+ *buffer++ = '+';
+ buflen--;
+ }
+ char tmp[46];
+ snprintf(tmp, sizeof(tmp), "%09u%09u%09u%09u%09u", vp->digits[4], vp->digits[3], vp->digits[2], vp->digits[1], vp->digits[0]);
+ if (leading_zeros) {
+ memset(buffer, '0', buflen);
+ uint32_t tocopy = __CFMin(sizeof(tmp), buflen);
+ memmove(buffer + buflen - tocopy, tmp + sizeof(tmp) - tocopy, tocopy); // copies trailing nul from tmp to nul-terminate
+ } else {
+ char *s = tmp;
+ while (*s == '0') s++;
+ if (*s == 0) s--; // if tmp is all zeros, copy out at least one zero
+ strlcpy(buffer, s, buflen);
+ }
+}
+
+void _CFBigNumFromCString(_CFBigNum *r, const char *string) {
+ memset(r, 0, sizeof(*r));
+ char *copy = (char *)calloc(strlen(string)+1, sizeof(char));
+ memcpy(copy, string, strlen(string)+1);
+ char *working = copy;
+ if (*working == '-') {
+ r->sign = -1;
+ working++;
+ } else if (*working == '+') {
+ working++;
+ }
+ while (*working == '0') {
+ working++;
+ }
+
+ size_t length = strlen(working);
+ if (length == 0) { // the number is zero
+ return;
+ }
+ int curDigit = 0;
+ while (curDigit + 1 < sizeof(r->digits) / sizeof(r->digits[0]) && 9 < length) {
+ uint32_t digit = atol(working+length-9);
+ r->digits[curDigit] = digit;
+ *(working+length-9) = 0;
+ length -= 9;
+ curDigit++;
+ }
+ uint32_t digit = atol(working);
+ r->digits[curDigit] = digit;
+ free(copy);
+}
+
+char *_CFBigNumCopyDescription(const _CFBigNum *num) {
+ char *result = (char *)calloc(1024, sizeof(char));
+ sprintf(result, "sign:%s 1st:%u 2nd:%u 3rd:%u 4th:%u 5th:%u", num->sign < 0 ? "-" : "+", num->digits[0], num->digits[1], num->digits[2], num->digits[3], num->digits[4]);
+ return result;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2012 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@
+ */
+
+/* CFBigNumber.h
+ Copyright (c) 2012-2012, Apple Inc. All rights reserved.
+*/
+
+#if !defined(__COREFOUNDATION_CFBIGNUMBER__)
+#define __COREFOUNDATION_CFBIGNUMBER__ 1
+
+#include <CoreFoundation/CFBase.h>
+#include <CoreFoundation/CFNumber.h>
+
+
+// Base 1 billion number: each digit represents 0 to 999999999
+typedef struct {
+ uint32_t digits[5];
+ int32_t sign:8;
+ uint32_t __:24;
+} _CFBigNum;
+
+void _CFBigNumInitWithInt8(_CFBigNum *r, int8_t inNum);
+void _CFBigNumInitWithInt16(_CFBigNum *r, int16_t inNum);
+void _CFBigNumInitWithInt32(_CFBigNum *r, int32_t inNum);
+void _CFBigNumInitWithInt64(_CFBigNum *r, int64_t inNum);
+#ifdef __LP64__
+void _CFBigNumInitWithInt128(_CFBigNum *r, __int128_t inNum);
+#endif
+
+void _CFBigNumInitWithUInt8(_CFBigNum *r, uint8_t inNum);
+void _CFBigNumInitWithUInt16(_CFBigNum *r, uint16_t inNum);
+void _CFBigNumInitWithUInt32(_CFBigNum *r, uint32_t inNum);
+void _CFBigNumInitWithUInt64(_CFBigNum *r, uint64_t inNum);
+#ifdef __LP64__
+void _CFBigNumInitWithUInt128(_CFBigNum *r, __uint128_t inNum);
+#endif
+
+int8_t _CFBigNumGetInt8(const _CFBigNum *num);
+int16_t _CFBigNumGetInt16(const _CFBigNum *num);
+int32_t _CFBigNumGetInt32(const _CFBigNum *num);
+int64_t _CFBigNumGetInt64(const _CFBigNum *num);
+#ifdef __LP64__
+__int128_t _CFBigNumGetInt128(const _CFBigNum *num);
+#endif
+
+uint8_t _CFBigNumGetUInt8(const _CFBigNum *num);
+uint16_t _CFBigNumGetUInt16(const _CFBigNum *num);
+uint32_t _CFBigNumGetUInt32(const _CFBigNum *num);
+uint64_t _CFBigNumGetUInt64(const _CFBigNum *num);
+#ifdef __LP64__
+__uint128_t _CFBigNumGetUInt128(const _CFBigNum *num);
+#endif
+
+void _CFBigNumInitWithCFNumber(_CFBigNum *r, CFNumberRef input);
+void _CFBigNumInitWithBytes(_CFBigNum *r, const void *bytes, CFNumberType type);
+CFNumberRef _CFNumberCreateWithBigNum(const _CFBigNum *input);
+
+
+CFComparisonResult _CFBigNumCompare(const _CFBigNum *a, const _CFBigNum *b);
+
+void _CFBigNumNeg(_CFBigNum *r, const _CFBigNum *a);
+uint8_t _CFBigNumAdd(_CFBigNum *r, const _CFBigNum *a, const _CFBigNum *b);
+uint8_t _CFBigNumSub(_CFBigNum *r, const _CFBigNum *a, const _CFBigNum *b);
+
+
+void _CFBigNumToCString(const _CFBigNum *vp, Boolean leading_zeros, Boolean leading_plus, char *buffer, size_t buflen);
+void _CFBigNumFromCString(_CFBigNum *r, const char *string);
+
+char *_CFBigNumCopyDescription(const _CFBigNum *num); // caller must free() returned ptr
+
+
+#endif /* ! __COREFOUNDATION_CFBIGNUMBER__ */
+
*/
/* CFBinaryHeap.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
*/
/* CFBinaryHeap.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
/*!
@header CFBinaryHeap
#include <CoreFoundation/CFBase.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
typedef struct {
CF_EXPORT void CFBinaryHeapRemoveAllValues(CFBinaryHeapRef heap);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFBINARYHEAP__ */
*/
/* CFBinaryPList.c
- Copyright (c) 2000-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2000-2012, Apple Inc. All rights reserved.
Responsibility: Tony Parker
*/
#include <CoreFoundation/CFPropertyList.h>
#include <CoreFoundation/CFByteOrder.h>
#include <CoreFoundation/CFRuntime.h>
+#include <CoreFoundation/CFUUID.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>
kCFNumberSInt128Type = 17
};
-CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number);
-__private_extern__ CFErrorRef __CFPropertyListCreateError(CFIndex code, CFStringRef debugString, ...);
-
enum {
CF_NO_ERROR = 0,
CF_OVERFLOW_ERROR = (1 << 0),
#define check_size_t_mul(b, a, err) (size_t)__check_uint32_mul_unsigned_unsigned((size_t)b, (size_t)a, err)
#endif
+#pragma mark -
+#pragma mark Keyed Archiver UID
struct __CFKeyedArchiverUID {
CFRuntimeBase _base;
return uid->_value;
}
+#pragma mark -
+#pragma mark Writing
+
+__private_extern__ CFErrorRef __CFPropertyListCreateError(CFIndex code, CFStringRef debugString, ...);
typedef struct {
CFTypeRef stream;
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]
OBJECT TABLE
variable-sized objects
Object Formats (marker byte followed by additional info in some cases)
- null 0000 0000
+ null 0000 0000 // null object [v1+ 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]
fill 0000 1111 // fill byte
- int 0001 nnnn ... // # of bytes is 2^nnnn, big-endian bytes
- real 0010 nnnn ... // # of bytes is 2^nnnn, big-endian bytes
+ int 0001 0nnn ... // # of bytes is 2^nnn, big-endian bytes
+ real 0010 0nnn ... // # of bytes is 2^nnn, big-endian bytes
date 0011 0011 ... // 8 byte float follows, big-endian bytes
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
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
- 1011 xxxx // unused
- set 1100 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]
dict 1101 nnnn [int] keyref* objref* // nnnn is count, unless '1111', then int count follows
1110 xxxx // unused
1111 xxxx // unused
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.
+
*/
static CFTypeID stringtype = -1, datatype = -1, numbertype = -1, datetype = -1;
-static CFTypeID booltype = -1, nulltype = -1, dicttype = -1, arraytype = -1, settype = -1;
+static CFTypeID booltype = -1, nulltype = -1, dicttype = -1, arraytype = -1;
+static CFTypeID uuidtype = -1, urltype = -1, osettype = -1, settype = -1;
static void initStatics() {
if ((CFTypeID)-1 == stringtype) {
if ((CFTypeID)-1 == nulltype) {
nulltype = CFNullGetTypeID();
}
+ if ((CFTypeID)-1 == uuidtype) {
+ uuidtype = CFUUIDGetTypeID();
+ }
+ if ((CFTypeID)-1 == urltype) {
+ urltype = CFURLGetTypeID();
+ }
+ if ((CFTypeID)-1 == osettype) {
+ osettype = -1;
+ }
}
static void _appendInt(__CFBinaryPlistWriteBuffer *buf, uint64_t bigint) {
bufferWrite(buf, bytes, nbytes);
}
+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);
+ // 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);
+ if (ret == count) {
+ uint8_t marker = (uint8_t)(kCFBinaryPlistMarkerASCIIString | (needed < 15 ? needed : 0xf));
+ bufferWrite(buf, &marker, 1);
+ if (15 <= needed) {
+ _appendInt(buf, (uint64_t)needed);
+ }
+ bufferWrite(buf, bytes, needed);
+ } else {
+ UniChar *chars;
+ uint8_t marker = (uint8_t)(kCFBinaryPlistMarkerUnicode16String | (count < 15 ? count : 0xf));
+ bufferWrite(buf, &marker, 1);
+ if (15 <= count) {
+ _appendInt(buf, (uint64_t)count);
+ }
+ chars = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, 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);
+ }
+ if (bytes != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, bytes);
+}
+
+CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number);
+
+static void _appendNumber(__CFBinaryPlistWriteBuffer *buf, CFNumberRef num) {
+ uint8_t marker;
+ uint64_t bigint;
+ uint8_t *bytes;
+ CFIndex nbytes;
+ if (CFNumberIsFloatType(num)) {
+ CFSwappedFloat64 swapped64;
+ CFSwappedFloat32 swapped32;
+ if (CFNumberGetByteSize(num) <= (CFIndex)sizeof(float)) {
+ float v;
+ CFNumberGetValue(num, kCFNumberFloat32Type, &v);
+ swapped32 = CFConvertFloat32HostToSwapped(v);
+ bytes = (uint8_t *)&swapped32;
+ nbytes = sizeof(float);
+ marker = kCFBinaryPlistMarkerReal | 2;
+ } else {
+ double v;
+ CFNumberGetValue(num, kCFNumberFloat64Type, &v);
+ swapped64 = CFConvertFloat64HostToSwapped(v);
+ bytes = (uint8_t *)&swapped64;
+ nbytes = sizeof(double);
+ marker = kCFBinaryPlistMarkerReal | 3;
+ }
+ bufferWrite(buf, &marker, 1);
+ bufferWrite(buf, bytes, nbytes);
+ } else {
+ CFNumberType type = _CFNumberGetType2(num);
+ if (kCFNumberSInt128Type == type) {
+ CFSInt128Struct s;
+ CFNumberGetValue(num, kCFNumberSInt128Type, &s);
+ struct {
+ int64_t high;
+ uint64_t low;
+ } storage;
+ storage.high = CFSwapInt64HostToBig(s.high);
+ storage.low = CFSwapInt64HostToBig(s.low);
+ uint8_t *bytes = (uint8_t *)&storage;
+ uint8_t marker = kCFBinaryPlistMarkerInt | 4;
+ CFIndex nbytes = 16;
+ bufferWrite(buf, &marker, 1);
+ bufferWrite(buf, bytes, nbytes);
+ } else {
+ CFNumberGetValue(num, kCFNumberSInt64Type, &bigint);
+ _appendInt(buf, bigint);
+ }
+ }
+}
+
+// 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;
+ CFTypeID type = CFGetTypeID(obj);
+ if (stringtype == type) {
+ _appendString(buf, (CFStringRef)obj);
+ } else if (numbertype == type) {
+ _appendNumber(buf, (CFNumberRef)obj);
+ } 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));
+ bufferWrite(buf, &marker, 1);
+ if (15 <= count) {
+ _appendInt(buf, (uint64_t)count);
+ }
+ bufferWrite(buf, CFDataGetBytePtr((CFDataRef)obj), count);
+ } else if (datetype == type) {
+ CFSwappedFloat64 swapped;
+ uint8_t marker = kCFBinaryPlistMarkerDate;
+ bufferWrite(buf, &marker, 1);
+ swapped = CFConvertFloat64HostToSwapped(CFDateGetAbsoluteTime((CFDateRef)obj));
+ bufferWrite(buf, (uint8_t *)&swapped, sizeof(swapped));
+ } else if (dicttype == type) {
+ CFIndex count = CFDictionaryGetCount((CFDictionaryRef)obj);
+ uint8_t marker = (uint8_t)(kCFBinaryPlistMarkerDict | (count < 15 ? count : 0xf));
+ bufferWrite(buf, &marker, 1);
+ if (15 <= count) {
+ _appendInt(buf, (uint64_t)count);
+ }
+ CFPropertyListRef *list, buffer[512];
+ list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, 2 * count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory);
+ CFDictionaryGetKeysAndValues((CFDictionaryRef)obj, list, list + count);
+ for (idx2 = 0; idx2 < 2 * 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 (arraytype == type) {
+ CFIndex count = CFArrayGetCount((CFArrayRef)obj);
+ CFPropertyListRef *list, buffer[256];
+ uint8_t marker = (uint8_t)(kCFBinaryPlistMarkerArray | (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);
+ CFArrayGetValues((CFArrayRef)obj, CFRangeMake(0, count), 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 && 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) {
+ _appendUID(buf, (CFKeyedArchiverUIDRef)obj);
+ } else {
+ return false;
+ }
+ return true;
+}
+
static void _flattenPlist(CFPropertyListRef plist, CFMutableArrayRef objlist, CFMutableDictionaryRef objtable, CFMutableSetRef uniquingset) {
CFPropertyListRef unique;
uint32_t refnum;
CF_INLINE uint8_t _byteCount(uint64_t count) {
uint64_t mask = ~(uint64_t)0;
uint8_t size = 0;
-
+
// Find something big enough to hold 'count'
while (count & mask) {
size++;
mask = mask << 8;
}
-
+
// Ensure that 'count' is a power of 2
// For sizes bigger than 8, just use the required count
while ((size != 1 && size != 2 && size != 4 && size != 8) && size <= 8) {
size++;
}
-
+
return size;
}
-
// stream can be a CFWriteStreamRef (on supported platforms) or a CFMutableDataRef
/* Write a property list to a stream, in binary format. plist is the property list to write (one of the basic property list types), stream is the destination of the property list, and estimate is a best-guess at the total number of objects in the property list. The estimate parameter is for efficiency in pre-allocating memory for the uniquing step. Pass in a 0 if no estimate is available. The options flag specifies sort options. If the error parameter is non-NULL and an error occurs, it will be used to return a CFError explaining the problem. It is the callers responsibility to release the error. */
CFIndex __CFBinaryPlistWrite(CFPropertyListRef plist, CFTypeRef stream, uint64_t estimate, CFOptionFlags options, CFErrorRef *error) {
- CFMutableDictionaryRef objtable;
- CFMutableArrayRef objlist;
- CFMutableSetRef uniquingset;
+ CFMutableDictionaryRef objtable = NULL;
+ CFMutableArrayRef objlist = NULL;
+ CFMutableSetRef uniquingset = NULL;
CFBinaryPlistTrailer trailer;
uint64_t *offsets, length_so_far;
- uint64_t refnum;
- int64_t idx, idx2, cnt;
+ int64_t idx, cnt;
__CFBinaryPlistWriteBuffer *buf;
initStatics();
trailer._topObject = 0; // true for this implementation
trailer._objectRefSize = _byteCount(cnt);
for (idx = 0; idx < cnt; idx++) {
- CFPropertyListRef obj = CFArrayGetValueAtIndex(objlist, (CFIndex)idx);
- CFTypeID type = CFGetTypeID(obj);
offsets[idx] = buf->written + buf->used;
- if (stringtype == type) {
- CFIndex ret, count = CFStringGetLength((CFStringRef)obj);
- CFIndex needed;
- uint8_t *bytes, buffer[1024];
- bytes = (count <= 1024) ? buffer : (uint8_t *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, 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((CFStringRef)obj, CFRangeMake(0, count), kCFStringEncodingASCII, 0, false, bytes, count, &needed);
- if (ret == count) {
- uint8_t marker = (uint8_t)(kCFBinaryPlistMarkerASCIIString | (needed < 15 ? needed : 0xf));
- bufferWrite(buf, &marker, 1);
- if (15 <= needed) {
- _appendInt(buf, (uint64_t)needed);
- }
- bufferWrite(buf, bytes, needed);
- } else {
- UniChar *chars;
- uint8_t marker = (uint8_t)(kCFBinaryPlistMarkerUnicode16String | (count < 15 ? count : 0xf));
- bufferWrite(buf, &marker, 1);
- if (15 <= count) {
- _appendInt(buf, (uint64_t)count);
- }
- chars = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, count * sizeof(UniChar), 0);
- CFStringGetCharacters((CFStringRef)obj, 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);
- }
- if (bytes != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, bytes);
- } else if (numbertype == type) {
- uint8_t marker;
- uint64_t bigint;
- uint8_t *bytes;
- CFIndex nbytes;
- if (CFNumberIsFloatType((CFNumberRef)obj)) {
- CFSwappedFloat64 swapped64;
- CFSwappedFloat32 swapped32;
- if (CFNumberGetByteSize((CFNumberRef)obj) <= (CFIndex)sizeof(float)) {
- float v;
- CFNumberGetValue((CFNumberRef)obj, kCFNumberFloat32Type, &v);
- swapped32 = CFConvertFloat32HostToSwapped(v);
- bytes = (uint8_t *)&swapped32;
- nbytes = sizeof(float);
- marker = kCFBinaryPlistMarkerReal | 2;
- } else {
- double v;
- CFNumberGetValue((CFNumberRef)obj, kCFNumberFloat64Type, &v);
- swapped64 = CFConvertFloat64HostToSwapped(v);
- bytes = (uint8_t *)&swapped64;
- nbytes = sizeof(double);
- marker = kCFBinaryPlistMarkerReal | 3;
- }
- bufferWrite(buf, &marker, 1);
- bufferWrite(buf, bytes, nbytes);
- } else {
- CFNumberType type = _CFNumberGetType2((CFNumberRef)obj);
- if (kCFNumberSInt128Type == type) {
- CFSInt128Struct s;
- CFNumberGetValue((CFNumberRef)obj, kCFNumberSInt128Type, &s);
- struct {
- int64_t high;
- uint64_t low;
- } storage;
- storage.high = CFSwapInt64HostToBig(s.high);
- storage.low = CFSwapInt64HostToBig(s.low);
- uint8_t *bytes = (uint8_t *)&storage;
- uint8_t marker = kCFBinaryPlistMarkerInt | 4;
- CFIndex nbytes = 16;
- bufferWrite(buf, &marker, 1);
- bufferWrite(buf, bytes, nbytes);
- } else {
- CFNumberGetValue((CFNumberRef)obj, kCFNumberSInt64Type, &bigint);
- _appendInt(buf, bigint);
- }
- }
- } else if (_CFKeyedArchiverUIDGetTypeID() == type) {
- _appendUID(buf, (CFKeyedArchiverUIDRef)obj);
- } else if (booltype == type) {
- uint8_t marker = CFBooleanGetValue((CFBooleanRef)obj) ? kCFBinaryPlistMarkerTrue : kCFBinaryPlistMarkerFalse;
- bufferWrite(buf, &marker, 1);
- } else if (datatype == type) {
- CFIndex count = CFDataGetLength((CFDataRef)obj);
- uint8_t marker = (uint8_t)(kCFBinaryPlistMarkerData | (count < 15 ? count : 0xf));
- bufferWrite(buf, &marker, 1);
- if (15 <= count) {
- _appendInt(buf, (uint64_t)count);
- }
- bufferWrite(buf, CFDataGetBytePtr((CFDataRef)obj), count);
- } else if (datetype == type) {
- CFSwappedFloat64 swapped;
- uint8_t marker = kCFBinaryPlistMarkerDate;
- bufferWrite(buf, &marker, 1);
- swapped = CFConvertFloat64HostToSwapped(CFDateGetAbsoluteTime((CFDateRef)obj));
- bufferWrite(buf, (uint8_t *)&swapped, sizeof(swapped));
- } else if (dicttype == type) {
- CFIndex count = CFDictionaryGetCount((CFDictionaryRef)obj);
-
- uint8_t marker = (uint8_t)(kCFBinaryPlistMarkerDict | (count < 15 ? count : 0xf));
- bufferWrite(buf, &marker, 1);
- if (15 <= count) {
- _appendInt(buf, (uint64_t)count);
- }
-
- CFPropertyListRef *list, buffer[512];
-
- list = (count <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, 2 * count * sizeof(CFTypeRef), __kCFAllocatorGCScannedMemory);
- CFDictionaryGetKeysAndValues((CFDictionaryRef)obj, list, list + count);
- for (idx2 = 0; idx2 < 2 * count; idx2++) {
- CFPropertyListRef value = list[idx2];
- 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) - trailer._objectRefSize, trailer._objectRefSize);
- }
- if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list);
- } else if (arraytype == type) {
- CFIndex count = CFArrayGetCount((CFArrayRef)obj);
- CFPropertyListRef *list, buffer[256];
- uint8_t marker = (uint8_t)(kCFBinaryPlistMarkerArray | (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);
- CFArrayGetValues((CFArrayRef)obj, CFRangeMake(0, count), list);
- for (idx2 = 0; idx2 < count; idx2++) {
- CFPropertyListRef value = list[idx2];
- 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) - trailer._objectRefSize, trailer._objectRefSize);
- }
- if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list);
- } else {
+ CFPropertyListRef obj = CFArrayGetValueAtIndex(objlist, (CFIndex)idx);
+ Boolean success = _appendObject(buf, obj, objtable, trailer._objectRefSize);
+ if (!success) {
CFRelease(objtable);
CFRelease(objlist);
if (error && buf->error) {
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
+
#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);
+
/* Grab a valSize-bytes integer out of the buffer pointed at by data and return it.
*/
CF_INLINE uint64_t _getSizedInt(const uint8_t *data, uint8_t valSize) {
CF_INLINE Boolean _plistIsPrimitive(CFPropertyListRef pl) {
CFTypeID type = CFGetTypeID(pl);
- if (dicttype == type || arraytype == type || settype == type) FAIL_FALSE;
+ if (dicttype == type || arraytype == type || settype == type || osettype == type) FAIL_FALSE;
return true;
}
return true;
}
-// Compatibility method, to be removed soon
-CF_EXPORT bool __CFBinaryPlistGetOffsetForValueFromDictionary2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFTypeRef key, uint64_t *koffset, uint64_t *voffset, CFMutableDictionaryRef objects) {
- return __CFBinaryPlistGetOffsetForValueFromDictionary3(databytes, datalen, startOffset, trailer, key, koffset, voffset, false, objects);
-}
-
/* Get the offset for a value in a dictionary in a binary property list.
@param databytes A pointer to the start of the binary property list data.
@param datalen The length of the data.
}
} else {
// temp object not saved in 'objects', because we don't know what allocator to use
- // (what allocator __CFBinaryPlistCreateObject2() or __CFBinaryPlistCreateObject()
+ // (what allocator __CFBinaryPlistCreateObjectFiltered() or __CFBinaryPlistCreateObject()
// will eventually be called with which results in that object)
keyInData = NULL;
- if (!__CFBinaryPlistCreateObject2(databytes, datalen, off, trailer, kCFAllocatorSystemDefault, kCFPropertyListImmutable, NULL /*objects*/, NULL, 0, &keyInData) || !_plistIsPrimitive(keyInData)) {
+ if (!__CFBinaryPlistCreateObjectFiltered(databytes, datalen, off, trailer, kCFAllocatorSystemDefault, kCFPropertyListImmutable, NULL /*objects*/, NULL, 0, NULL, &keyInData) || !_plistIsPrimitive(keyInData)) {
if (keyInData) CFRelease(keyInData);
return 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_EXPORT bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFPropertyListRef *plist) {
+__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) {
if (objects) {
*plist = CFDictionaryGetValue(objects, (const void *)(uintptr_t)startOffset);
int32_t err = CF_NO_ERROR;
ptr = check_ptr_add(ptr, 1, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
- CFIndex cnt = marker & 0x0f;
- if (0xf == cnt) {
+ CFIndex arrayCount = marker & 0x0f;
+ if (0xf == arrayCount) {
uint64_t bigint = 0;
if (!_readInt(ptr, databytes + objectsRangeEnd, &bigint, &ptr)) FAIL_FALSE;
if (LONG_MAX < bigint) FAIL_FALSE;
- cnt = (CFIndex)bigint;
+ arrayCount = (CFIndex)bigint;
}
- size_t byte_cnt = check_size_t_mul(cnt, trailer->_objectRefSize, &err);
+ size_t byte_cnt = check_size_t_mul(arrayCount, trailer->_objectRefSize, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
const uint8_t *extent = check_ptr_add(ptr, byte_cnt, &err) - 1;
if (CF_NO_ERROR != err) FAIL_FALSE;
if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
- byte_cnt = check_size_t_mul(cnt, sizeof(CFPropertyListRef), &err);
+ byte_cnt = check_size_t_mul(arrayCount, sizeof(CFPropertyListRef), &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
- list = (cnt <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, byte_cnt, __kCFAllocatorGCScannedMemory);
+ list = (arrayCount <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, byte_cnt, __kCFAllocatorGCScannedMemory);
if (!list) FAIL_FALSE;
Boolean madeSet = false;
if (!set && 15 < curDepth) {
set = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
madeSet = set ? true : false;
}
- if (set) CFSetAddValue(set, (const void *)(uintptr_t)startOffset);
- for (CFIndex idx = 0; idx < cnt; idx++) {
- CFPropertyListRef pl;
- off = _getOffsetOfRefAt(databytes, ptr, trailer);
- if (!__CFBinaryPlistCreateObject2(databytes, datalen, off, trailer, allocator, mutabilityOption, objects, set, curDepth + 1, &pl)) {
- while (idx--) {
- if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]);
- }
- if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list);
- FAIL_FALSE;
- }
- __CFAssignWithWriteBarrier((void **)list + idx, (void *)pl);
- ptr += trailer->_objectRefSize;
- }
- if (set) CFSetRemoveValue(set, (const void *)(uintptr_t)startOffset);
- if (madeSet) {
- CFRelease(set);
- set = NULL;
- }
- if ((marker & 0xf0) == kCFBinaryPlistMarkerArray) {
- if (mutabilityOption != kCFPropertyListImmutable) {
- *plist = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
- CFArrayReplaceValues((CFMutableArrayRef)*plist, CFRangeMake(0, 0), list, cnt);
- for (CFIndex idx = 0; idx < cnt; idx++) {
- if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]);
- }
- } else {
- if (!kCFUseCollectableAllocator) {
- *plist = __CFArrayCreateTransfer(allocator, list, cnt);
- } else {
- *plist = CFArrayCreate(allocator, list, cnt, &kCFTypeArrayCallBacks);
- for (CFIndex idx = 0; idx < cnt; idx++) {
- if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]);
+
+ if (set) CFSetAddValue(set, (const void *)(uintptr_t)startOffset);
+ if ((marker & 0xf0) == kCFBinaryPlistMarkerArray && keyPaths) {
+ // Only get a subset of this array
+ CFSetRef theseKeys, nextKeys;
+ __CFPropertyListCreateSplitKeypaths(kCFAllocatorSystemDefault, keyPaths, &theseKeys, &nextKeys);
+
+ Boolean success = true;
+ CFMutableArrayRef array = CFArrayCreateMutable(allocator, CFSetGetCount(theseKeys), &kCFTypeArrayCallBacks);
+ if (theseKeys) {
+ CFTypeRef *keys = (CFTypeRef *)malloc(CFSetGetCount(theseKeys) * sizeof(CFTypeRef));
+ CFSetGetValues(theseKeys, keys);
+ for (CFIndex i = 0; i < CFSetGetCount(theseKeys); i++) {
+ CFStringRef key = (CFStringRef)keys[i];
+ SInt32 intValue = CFStringGetIntValue(key);
+ if ((intValue == 0 && CFStringCompare(CFSTR("0"), key, 0) != kCFCompareEqualTo) || intValue == INT_MAX || intValue == INT_MIN || intValue < 0) {
+ // skip, doesn't appear to be a proper integer
+ } else {
+ uint64_t valueOffset;
+ Boolean found = __CFBinaryPlistGetOffsetForValueFromArray2(databytes, datalen, startOffset, trailer, (CFIndex)intValue, &valueOffset, objects);
+ if (found) {
+ CFPropertyListRef result;
+ success = __CFBinaryPlistCreateObjectFiltered(databytes, datalen, valueOffset, trailer, allocator, mutabilityOption, objects, set, curDepth + 1, nextKeys, &result);
+ if (success) {
+ CFArrayAppendValue(array, result);
+ CFRelease(result);
+ } else {
+ break;
+ }
+ }
}
}
- }
- } else {
- if (mutabilityOption != kCFPropertyListImmutable) {
- *plist = CFSetCreateMutable(allocator, 0, &kCFTypeSetCallBacks);
- for (CFIndex idx = 0; idx < cnt; idx++) {
- CFSetAddValue((CFMutableSetRef)*plist, list[idx]);
- }
- for (CFIndex idx = 0; idx < cnt; idx++) {
- if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]);
- }
- } else {
- if (!kCFUseCollectableAllocator) {
- *plist = __CFSetCreateTransfer(allocator, list, cnt);
+
+ free(keys);
+ CFRelease(theseKeys);
+ }
+ if (nextKeys) CFRelease(nextKeys);
+
+ if (success) {
+ if (!(mutabilityOption == kCFPropertyListMutableContainers || mutabilityOption == kCFPropertyListMutableContainersAndLeaves)) {
+ // make immutable
+ *plist = CFArrayCreateCopy(allocator, array);
+ if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(array);
} else {
- *plist = CFSetCreate(allocator, list, cnt, &kCFTypeSetCallBacks);
- for (CFIndex idx = 0; idx < cnt; idx++) {
+ *plist = array;
+ }
+ } else if (array) {
+ if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(array);
+ }
+ } else {
+ for (CFIndex idx = 0; idx < arrayCount; idx++) {
+ CFPropertyListRef pl;
+ 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]);
+ }
+ if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list);
+ FAIL_FALSE;
+ }
+ __CFAssignWithWriteBarrier((void **)list + idx, (void *)pl);
+ ptr += trailer->_objectRefSize;
+ }
+ if ((marker & 0xf0) == kCFBinaryPlistMarkerArray) {
+ if (mutabilityOption != kCFPropertyListImmutable) {
+ *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]);
+ }
+ } else {
+ if (!kCFUseCollectableAllocator) {
+ *plist = __CFArrayCreateTransfer(allocator, list, arrayCount);
+ } else {
+ *plist = CFArrayCreate(allocator, list, arrayCount, &kCFTypeArrayCallBacks);
+ for (CFIndex idx = 0; idx < arrayCount; idx++) {
+ if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]);
+ }
}
}
- }
- }
+ } else {
+ if (mutabilityOption != kCFPropertyListImmutable) {
+ *plist = CFSetCreateMutable(allocator, 0, &kCFTypeSetCallBacks);
+ for (CFIndex idx = 0; idx < arrayCount; idx++) {
+ CFSetAddValue((CFMutableSetRef)*plist, list[idx]);
+ }
+ for (CFIndex idx = 0; idx < arrayCount; idx++) {
+ if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]);
+ }
+ } else {
+ if (!kCFUseCollectableAllocator) {
+ *plist = __CFSetCreateTransfer(allocator, list, arrayCount);
+ } else {
+ *plist = CFSetCreate(allocator, list, arrayCount, &kCFTypeSetCallBacks);
+ for (CFIndex idx = 0; idx < arrayCount; idx++) {
+ if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]);
+ }
+ }
+ }
+ }
+ }
+ if (set) CFSetRemoveValue(set, (const void *)(uintptr_t)startOffset);
+ if (madeSet) {
+ CFRelease(set);
+ set = NULL;
+ }
if (objects && *plist && (mutabilityOption == kCFPropertyListImmutable)) {
CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
}
int32_t err = CF_NO_ERROR;
ptr = check_ptr_add(ptr, 1, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
- CFIndex cnt = marker & 0x0f;
- if (0xf == cnt) {
+ CFIndex dictionaryCount = marker & 0x0f;
+ if (0xf == dictionaryCount) {
uint64_t bigint = 0;
if (!_readInt(ptr, databytes + objectsRangeEnd, &bigint, &ptr)) FAIL_FALSE;
if (LONG_MAX < bigint) FAIL_FALSE;
- cnt = (CFIndex)bigint;
+ dictionaryCount = (CFIndex)bigint;
}
- cnt = check_size_t_mul(cnt, 2, &err);
+ dictionaryCount = check_size_t_mul(dictionaryCount, 2, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
- size_t byte_cnt = check_size_t_mul(cnt, trailer->_objectRefSize, &err);
+ size_t byte_cnt = check_size_t_mul(dictionaryCount, trailer->_objectRefSize, &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
const uint8_t *extent = check_ptr_add(ptr, byte_cnt, &err) - 1;
if (CF_NO_ERROR != err) FAIL_FALSE;
if (databytes + objectsRangeEnd < extent) FAIL_FALSE;
- byte_cnt = check_size_t_mul(cnt, sizeof(CFPropertyListRef), &err);
+ byte_cnt = check_size_t_mul(dictionaryCount, sizeof(CFPropertyListRef), &err);
if (CF_NO_ERROR != err) FAIL_FALSE;
- list = (cnt <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, byte_cnt, __kCFAllocatorGCScannedMemory);
+ list = (dictionaryCount <= 256) ? buffer : (CFPropertyListRef *)CFAllocatorAllocate(kCFAllocatorSystemDefaultGCRefZero, byte_cnt, __kCFAllocatorGCScannedMemory);
if (!list) FAIL_FALSE;
Boolean madeSet = false;
if (!set && 15 < curDepth) {
set = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
madeSet = set ? true : false;
}
- if (set) CFSetAddValue(set, (const void *)(uintptr_t)startOffset);
- for (CFIndex idx = 0; idx < cnt; idx++) {
- CFPropertyListRef pl = NULL;
- off = _getOffsetOfRefAt(databytes, ptr, trailer);
- if (!__CFBinaryPlistCreateObject2(databytes, datalen, off, trailer, allocator, mutabilityOption, objects, set, curDepth + 1, &pl) || (idx < cnt / 2 && !_plistIsPrimitive(pl))) {
- if (pl && !_CFAllocatorIsGCRefZero(allocator)) CFRelease(pl);
- while (idx--) {
+
+ if (set) CFSetAddValue(set, (const void *)(uintptr_t)startOffset);
+ if (keyPaths) {
+ // Only get a subset of this dictionary
+ CFSetRef theseKeys, nextKeys;
+ __CFPropertyListCreateSplitKeypaths(kCFAllocatorSystemDefault, keyPaths, &theseKeys, &nextKeys);
+
+ Boolean success = true;
+ CFMutableDictionaryRef dict = CFDictionaryCreateMutable(allocator, CFSetGetCount(theseKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (theseKeys) {
+ CFTypeRef *keys = (CFTypeRef *)malloc(CFSetGetCount(theseKeys) * sizeof(CFTypeRef));
+ CFSetGetValues(theseKeys, keys);
+ for (CFIndex i = 0; i < CFSetGetCount(theseKeys); i++) {
+ CFStringRef key = (CFStringRef)keys[i];
+ uint64_t keyOffset, valueOffset;
+ Boolean found = __CFBinaryPlistGetOffsetForValueFromDictionary3(databytes, datalen, startOffset, trailer, key, &keyOffset, &valueOffset, false, objects);
+ if (found) {
+ CFPropertyListRef result;
+ success = __CFBinaryPlistCreateObjectFiltered(databytes, datalen, valueOffset, trailer, allocator, mutabilityOption, objects, set, curDepth + 1, nextKeys, &result);
+ if (success) {
+ CFDictionarySetValue(dict, key, result);
+ CFRelease(result);
+ } else {
+ break;
+ }
+ }
+ }
+
+ free(keys);
+ CFRelease(theseKeys);
+ }
+ if (nextKeys) CFRelease(nextKeys);
+
+ if (success) {
+ if (!(mutabilityOption == kCFPropertyListMutableContainers || mutabilityOption == kCFPropertyListMutableContainersAndLeaves)) {
+ // make immutable
+ *plist = CFDictionaryCreateCopy(allocator, dict);
+ if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(dict);
+ } else {
+ *plist = dict;
+ }
+ } else if (dict) {
+ if (!_CFAllocatorIsGCRefZero(allocator)) 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);
+ while (idx--) {
+ if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]);
+ }
+ if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list);
+ FAIL_FALSE;
+ }
+ __CFAssignWithWriteBarrier((void **)list + idx, (void *)pl);
+ ptr += trailer->_objectRefSize;
+ }
+ if (mutabilityOption != kCFPropertyListImmutable) {
+ *plist = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ for (CFIndex idx = 0; idx < dictionaryCount / 2; idx++) {
+ CFDictionaryAddValue((CFMutableDictionaryRef)*plist, list[idx], list[idx + dictionaryCount / 2]);
+ }
+ for (CFIndex idx = 0; idx < dictionaryCount; idx++) {
if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]);
- }
- if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefaultGCRefZero, list);
- FAIL_FALSE;
- }
- __CFAssignWithWriteBarrier((void **)list + idx, (void *)pl);
- ptr += trailer->_objectRefSize;
- }
- if (set) CFSetRemoveValue(set, (const void *)(uintptr_t)startOffset);
- if (madeSet) {
- CFRelease(set);
- set = NULL;
- }
- if (mutabilityOption != kCFPropertyListImmutable) {
- *plist = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- for (CFIndex idx = 0; idx < cnt / 2; idx++) {
- CFDictionaryAddValue((CFMutableDictionaryRef)*plist, list[idx], list[idx + cnt / 2]);
- }
- for (CFIndex idx = 0; idx < cnt; idx++) {
- if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]);
- }
- } else {
- if (!kCFUseCollectableAllocator) {
- *plist = __CFDictionaryCreateTransfer(allocator, list, list + cnt / 2, cnt / 2);
+ }
} else {
- *plist = CFDictionaryCreate(allocator, list, list + cnt / 2, cnt / 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- for (CFIndex idx = 0; idx < cnt; idx++) {
- if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(list[idx]);
- }
- }
- }
+ if (!kCFUseCollectableAllocator) {
+ *plist = __CFDictionaryCreateTransfer(allocator, list, list + dictionaryCount / 2, dictionaryCount / 2);
+ } 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]);
+ }
+ }
+ }
+ }
+ if (set) CFSetRemoveValue(set, (const void *)(uintptr_t)startOffset);
+ if (madeSet) {
+ CFRelease(set);
+ set = NULL;
+ }
if (objects && *plist && (mutabilityOption == kCFPropertyListImmutable)) {
CFDictionarySetValue(objects, (const void *)(uintptr_t)startOffset, *plist);
}
bool __CFBinaryPlistCreateObject(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFPropertyListRef *plist) {
// for compatibility with Foundation's use, need to leave this here
- return __CFBinaryPlistCreateObject2(databytes, datalen, startOffset, trailer, allocator, mutabilityOption, objects, NULL, 0, plist);
+ 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) {
CFMutableDictionaryRef objects = CFDictionaryCreateMutable(kCFAllocatorSystemDefaultGCRefZero, 0, NULL, &kCFTypeDictionaryValueCallBacks);
_CFDictionarySetCapacity(objects, trailer._numObjects);
CFPropertyListRef pl = NULL;
- if (__CFBinaryPlistCreateObject2(databytes, datalen, offset, &trailer, allocator, option, objects, NULL, 0, &pl)) {
+ bool result = true;
+ if (__CFBinaryPlistCreateObjectFiltered(databytes, datalen, offset, &trailer, allocator, option, objects, NULL, 0, NULL, &pl)) {
if (plist) *plist = pl;
} else {
if (plist) *plist = NULL;
if (errorString) *errorString = (CFStringRef)CFRetain(CFSTR("binary data is corrupt"));
+ result = false;
}
if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(objects);
- return true;
+ 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;
+}
+
*/
/* CFBitVector.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
to right (bit 0 is the most significant) */
typedef uint8_t __CFBitVectorBucket;
+#define __CFBITVECTORBUCKET_SIZE 8
+#define __CF_BITS_PER_BYTE 8
+
enum {
- __CF_BITS_PER_BYTE = 8,
__CF_BITS_PER_BYTE_MASK = 0x07
};
context->curByte++;
context->totalBits -= context->initBits;
nBits -= __CF_BITS_PER_BYTE;
+#if __CFBITVECTORBUCKET_SIZE > __CF_BITS_PER_BYTE
val <<= __CF_BITS_PER_BYTE;
+#else
+ val = 0;
+#endif
}
/* ... then remaining bits go in *curByte */
if (0 < nBits) {
*/
/* CFBitVector.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFBITVECTOR__)
#include <CoreFoundation/CFBase.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
typedef UInt32 CFBit;
CF_EXPORT void CFBitVectorSetAllBits(CFMutableBitVectorRef bv, CFBit value);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFBITVECTOR__ */
*/
/* CFBuiltinConverters.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Aki Inoue
*/
static int8_t __CFMapsParagraphSeparator = -1;
CF_INLINE bool __CFIsParagraphSeparator(UTF16Char character) {
- if (-1 == __CFMapsParagraphSeparator) __CFMapsParagraphSeparator = (_CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard) ? false : true);
+ if (-1 == __CFMapsParagraphSeparator) __CFMapsParagraphSeparator = (1 ? false : true);
return ((__CFMapsParagraphSeparator && (ParagraphSeparator == character)) ? true : false);
}
*/
/* CFBundle.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
- Responsibility: David Smith
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
+ Responsibility: Tony Parker
*/
#include "CFBundle_Internal.h"
#include <sys/stat.h>
#include <stdlib.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS
+#else
+#error Unknown deployment target
+#endif
+
#define AVOID_WEAK_COLLECTIONS 1
-#if !defined(AVOID_WEAK_COLLECTIONS)
+#if !AVOID_WEAK_COLLECTIONS
#include "CFHashTable.h"
#include "CFMapTable.h"
#include "CFPointerArray.h"
#include <dlfcn.h>
#endif /* BINARY_SUPPORT_DLFCN */
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#include <fcntl.h>
#elif DEPLOYMENT_TARGET_WINDOWS
#include <fcntl.h>
#define open _NS_open
#define stat(x,y) _NS_stat(x,y)
+#endif
+
+#if DEPLOYMENT_TARGET_WINDOWS
+#define statinfo _stat
+
+// Windows isspace implementation limits the input chars to < 256 in the ASCII range. It will
+// assert in debug builds. This is annoying. We merrily grok chars > 256.
+static inline BOOL isspace(char c) {
+ return (c == ' ' || c == '\t' || c == '\n' || c == '\r'|| c == '\v' || c == '\f');
+}
#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
+#define statinfo stat
#endif
-extern void _processInfoDictionary(CFMutableDictionaryRef dict, CFStringRef platformSuffix, CFStringRef productSuffix);
-extern CFStringRef _CFGetProductName(void);
-extern CFStringRef _CFGetPlatformName(void);
-extern CFStringRef _CFGetAlternatePlatformName(void);
+__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);
_CFPlugInData _plugInData;
- CFSpinLock_t _bundleLoadingLock;
+ 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 CFSpinLock_t CFBundleGlobalDataLock = CFSpinLockInit;
+static pthread_mutex_t CFBundleGlobalDataLock = PTHREAD_MUTEX_INITIALIZER;
static CFMutableDictionaryRef _bundlesByIdentifier = NULL;
-#if defined(AVOID_WEAK_COLLECTIONS)
+#if AVOID_WEAK_COLLECTIONS
static CFMutableDictionaryRef _bundlesByURL = NULL;
static CFMutableArrayRef _allBundles = NULL;
static CFMutableSetRef _bundlesToUnload = NULL;
static CFURLRef _CFBundleCopyExecutableURLIgnoringCache(CFBundleRef bundle);
static void _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(CFStringRef hint);
static void _CFBundleEnsureAllBundlesUpToDateAlreadyLocked(void);
-static void _CFBundleCheckWorkarounds(CFBundleRef bundle);
static void _CFBundleEnsureBundleExistsForImagePath(CFStringRef imagePath);
static void _CFBundleEnsureBundlesExistForImagePaths(CFArrayRef imagePaths);
#if defined(BINARY_SUPPORT_DYLD)
#endif /* BINARY_SUPPORT_DLFCN */
-#if defined(AVOID_WEAK_COLLECTIONS)
+#if AVOID_WEAK_COLLECTIONS
static void _CFBundleAddToTables(CFBundleRef bundle, Boolean alreadyLocked) {
CFStringRef bundleID = CFBundleGetIdentifier(bundle);
- if (!alreadyLocked) __CFSpinLock(&CFBundleGlobalDataLock);
+ if (!alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock);
// Add to the _allBundles list
if (!_allBundles) {
CFRelease(bundlesWithThisID);
}
}
- if (!alreadyLocked) __CFSpinUnlock(&CFBundleGlobalDataLock);
+ if (!alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock);
}
static void _CFBundleRemoveFromTables(CFBundleRef bundle, CFURLRef bundleURL, CFStringRef bundleID) {
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
// Remove from the various lists
if (_allBundles) {
CFIndex i = CFArrayGetFirstIndexOfValue(_allBundles, CFRangeMake(0, CFArrayGetCount(_allBundles)), bundle);
if (0 == CFArrayGetCount(bundlesWithThisID)) CFDictionaryRemoveValue(_bundlesByIdentifier, bundleID);
}
}
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
}
static CFBundleRef _CFBundleCopyBundleForURL(CFURLRef url, Boolean alreadyLocked) {
CFBundleRef result = NULL;
- if (!alreadyLocked) __CFSpinLock(&CFBundleGlobalDataLock);
+ if (!alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock);
if (_bundlesByURL) result = (CFBundleRef)CFDictionaryGetValue(_bundlesByURL, url);
if (result && !result->_url) {
result = NULL;
CFDictionaryRemoveValue(_bundlesByURL, url);
}
if (result) CFRetain(result);
- if (!alreadyLocked) __CFSpinUnlock(&CFBundleGlobalDataLock);
+ if (!alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock);
return result;
}
static void _CFBundleAddToTables(CFBundleRef bundle, Boolean alreadyLocked) {
CFStringRef bundleID = CFBundleGetIdentifier(bundle);
- if (!alreadyLocked) __CFSpinLock(&CFBundleGlobalDataLock);
+ if (!alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock);
// Add to the _allBundles list
if (!_allBundles) _allBundles = [[__CFHashTable alloc] initWithOptions:CFPointerFunctionsZeroingWeakMemory capacity:0];
[bundlesWithThisID release];
}
}
- if (!alreadyLocked) __CFSpinUnlock(&CFBundleGlobalDataLock);
+ if (!alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock);
}
static void _CFBundleRemoveFromTables(CFBundleRef bundle, CFURLRef bundleURL, CFStringRef bundleID) {
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
// Remove from the various lists
if (_allBundles && [_allBundles member:(id)bundle]) [_allBundles removeObject:(id)bundle];
if (0 == [bundlesWithThisID count]) CFDictionaryRemoveValue(_bundlesByIdentifier, bundleID);
}
}
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
}
static CFBundleRef _CFBundleCopyBundleForURL(CFURLRef url, Boolean alreadyLocked) {
CFBundleRef result = NULL;
- if (!alreadyLocked) __CFSpinLock(&CFBundleGlobalDataLock);
+ if (!alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock);
result = _getFromBundlesByURL(url);
if (result && !result->_url) {
result = NULL;
_removeFromBundlesByURL(url);
}
if (result) CFRetain(result);
- if (!alreadyLocked) __CFSpinUnlock(&CFBundleGlobalDataLock);
+ if (!alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock);
return result;
}
#endif /* AVOID_WEAK_COLLECTIONS */
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
-#endif
-
static CFURLRef _CFBundleCopyBundleURLForExecutablePath(CFStringRef str) {
//!!! need to handle frameworks, NT; need to integrate with NSBundle - drd
UniChar buff[CFMaxPathSize];
if (buffLen > CFMaxPathSize) buffLen = CFMaxPathSize;
CFStringGetCharacters(str, CFRangeMake(0, buffLen), buff);
-#if DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_WINDOWS
// Is this a .dll or .exe?
if (buffLen >= 5 && (_wcsnicmp((wchar_t *)&(buff[buffLen-4]), L".dll", 4) == 0 || _wcsnicmp((wchar_t *)&(buff[buffLen-4]), L".exe", 4) == 0)) {
CFIndex extensionLength = CFStringGetLength(_CFBundleWindowsResourceDirectoryExtension);
CFRelease(outstr);
}
}
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
if (!url) {
buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen); // Remove exe name
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
if (buffLen > 0) {
// See if this is a new bundle. If it is, we have to remove more path components.
CFIndex startOfLastDir = _CFStartOfLastPathComponent(buff, buffLen);
if (buffLen > 0) {
// Remove support files folder
buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
-#endif
}
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
CFRelease(lastDirName);
}
}
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
-#endif
if (buffLen > 0) {
outstr = CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault, buff, buffLen, kCFAllocatorNull);
}
if (bundle == _mainBundle) {
CFStringRef executablePath = oldInfoDict ? (CFStringRef)CFDictionaryGetValue(oldInfoDict, _kCFBundleExecutablePathKey) : NULL;
- if (!alreadyLocked) __CFSpinLock(&CFBundleGlobalDataLock);
+ if (!alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock);
_CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(executablePath);
- if (!alreadyLocked) __CFSpinUnlock(&CFBundleGlobalDataLock);
+ if (!alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock);
} else {
CFBundleGetInfoDictionary(bundle);
}
_CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(str);
// Perform delayed final processing steps.
// This must be done after _isLoaded has been set, for security reasons (3624341).
- _CFBundleCheckWorkarounds(_mainBundle);
if (_CFBundleNeedsInitPlugIn(_mainBundle)) {
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
_CFBundleInitPlugIn(_mainBundle);
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
}
}
}
CFBundleRef CFBundleGetMainBundle(void) {
CFBundleRef mainBundle;
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
mainBundle = _CFBundleGetMainBundleAlreadyLocked();
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
return mainBundle;
}
CFBundleRef CFBundleGetBundleWithIdentifier(CFStringRef bundleID) {
CFBundleRef result = NULL;
if (bundleID) {
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
(void)_CFBundleGetMainBundleAlreadyLocked();
result = _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (!result) {
// Try to create the bundle for the caller and try again
void *p = __builtin_return_address(0);
result = _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID);
}
}
-#elif DEPLOYMENT_TARGET_WINDOWS
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
if (!result) {
// Try to guess the bundle from the identifier and try again
_CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
result = _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID);
}
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
}
return result;
}
CFRelease(bundle->_glueDict);
}
if (bundle->_resourceData._stringTableCache) CFRelease(bundle->_resourceData._stringTableCache);
+
+ // ZFH
+ if (bundle->_bundleBasePath) CFRelease(bundle->_bundleBasePath);
+ if (bundle->_queryTable) CFRelease(bundle->_queryTable);
+
+ pthread_mutex_destroy(&(bundle->_bundleLoadingLock));
}
static const CFRuntimeClass __CFBundleClass = {
};
// From CFBundle_Resources.c
-void _CFBundleResourcesInitialize();
+__private_extern__ void _CFBundleResourcesInitialize();
__private_extern__ void __CFBundleInitialize(void) {
__kCFBundleTypeID = _CFRuntimeRegisterClass(&__CFBundleClass);
bundle->_isLoaded = false;
bundle->_sharesStringsFiles = false;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (!__CFgetenv("CFBundleDisableStringsSharing") &&
(strncmp(buff, "/System/Library/Frameworks", 26) == 0) &&
(strncmp(buff + strlen(buff) - 10, ".framework", 10) == 0)) bundle->_sharesStringsFiles = true;
-#elif DEPLOYMENT_TARGET_WINDOWS
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
bundle->_connectionCookie = NULL;
bundle->_plugInData._instanceCount = 0;
bundle->_plugInData._factories = NULL;
- bundle->_bundleLoadingLock = CFSpinLockInit;
+ pthread_mutexattr_t mattr;
+ pthread_mutexattr_init(&mattr);
+ pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_DEFAULT);
+ int32_t mret = pthread_mutex_init(&(bundle->_bundleLoadingLock), &mattr);
+ pthread_mutexattr_destroy(&mattr);
+ if (0 != mret) {
+ CFLog(4, CFSTR("%s: failed to initialize bundle loading lock for bundle %@."), __PRETTY_FUNCTION__, bundle);
+ }
+
+ // ZFH
+ /* resource fast look up */
+ bundle->_queryLock = CFSpinLockInit;
+ bundle->_queryTable = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFURLRef absoURL = CFURLCopyAbsoluteURL(bundle->_url);
+ bundle->_bundleBasePath = CFURLCopyFileSystemPath(absoURL, PLATFORM_PATH_STYLE);
+ CFRelease(absoURL);
CFBundleGetInfoDictionary(bundle);
_CFBundleAddToTables(bundle, alreadyLocked);
if (doFinalProcessing) {
- _CFBundleCheckWorkarounds(bundle);
if (_CFBundleNeedsInitPlugIn(bundle)) {
- if (alreadyLocked) __CFSpinUnlock(&CFBundleGlobalDataLock);
+ if (alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock);
_CFBundleInitPlugIn(bundle);
- if (alreadyLocked) __CFSpinLock(&CFBundleGlobalDataLock);
+ if (alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock);
}
}
}
CFDictionaryRef CFBundleGetLocalInfoDictionary(CFBundleRef bundle) {
- static CFSpinLock_t CFBundleLocalInfoLock = CFSpinLockInit;
+ static pthread_mutex_t CFBundleLocalInfoLock = PTHREAD_MUTEX_INITIALIZER;
CFDictionaryRef localInfoDict = bundle->_localInfoDict;
if (!localInfoDict) {
CFURLRef url = CFBundleCopyResourceURL(bundle, _CFBundleLocalInfoName, _CFBundleStringTableType, NULL);
CFRelease(url);
}
if (localInfoDict) _processInfoDictionary((CFMutableDictionaryRef)localInfoDict, _CFGetPlatformName(), _CFGetProductName());
- __CFSpinLock(&CFBundleLocalInfoLock);
+ pthread_mutex_lock(&CFBundleLocalInfoLock);
if (!bundle->_localInfoDict) {
bundle->_localInfoDict = localInfoDict;
} else {
if (localInfoDict && !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(localInfoDict);
localInfoDict = bundle->_localInfoDict;
}
- __CFSpinUnlock(&CFBundleLocalInfoLock);
+ pthread_mutex_unlock(&CFBundleLocalInfoLock);
}
return localInfoDict;
}
// See <rdar://problem/6956670>
static Boolean _binaryLoadable(CFURLRef url) {
Boolean loadable = _urlExists(url);
-#if DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (!loadable) {
uint8_t path[PATH_MAX];
if (url && CFURLGetFileSystemRepresentation(url, true, path, sizeof(path))) {
CFURLRef executableURL = NULL;
if (!urlPath || !exeName) return NULL;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
const uint8_t *image_suffix = (uint8_t *)__CFgetenv("DYLD_IMAGE_SUFFIX");
if (image_suffix) {
CFStringRef newExeName, imageSuffix;
CFRelease(newExeName);
}
}
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
return executableURL;
}
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 = CFBundleCopyResourceURL(bundle, executableName, CFSTR("rsrc"), NULL);
+ resourceForkURL = (CFURLRef) _CFBundleCopyFindResourcesWithNoBlock(bundle, NULL, NULL, executableName, type, NULL, NULL, NO, NO);
} else {
- resourceForkURL = CFBundleCopyResourceURLForLocalization(bundle, executableName, CFSTR("rsrc"), NULL, NULL);
+ 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);
}
if (executablePath) CFRetain(executablePath);
__CFSpinUnlock(&CFBundleExecutablePathLock);
if (executablePath) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#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);
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
if (executableURL) {
foundIt = true;
if (!foundIt) {
if (lookupMainExe) executableName = _CFBundleCopyExecutableName(bundle, url, infoDict);
if (executableName) {
-#if DEPLOYMENT_TARGET_EMBEDDED
+#if (DEPLOYMENT_TARGET_EMBEDDED && !TARGET_IPHONE_SIMULATOR)
Boolean doExecSearch = false;
#else
Boolean doExecSearch = true;
#endif
// Now, look for the executable inside the bundle.
if (doExecSearch && 0 != version) {
- CFURLRef exeDirURL;
+ CFURLRef exeDirURL = NULL;
CFURLRef exeSubdirURL;
if (1 == version) {
} else {
exeDirURL = (CFURLRef)CFRetain(url);
}
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
exeDirURL = (CFURLRef)CFRetain(url);
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
}
CFStringRef platformSubDir = useOtherPlatform ? _CFBundleGetOtherPlatformExecutablesSubdirectoryName() : _CFBundleGetPlatformExecutablesSubdirectoryName();
executableURL = _CFBundleCopyExecutableURLRaw(exeDirURL, executableName);
CFRelease(exeDirURL);
}
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
if (lookupMainExe && !ignoreCache && !useOtherPlatform && bundle && infoDict && executableURL) {
CFURLRef absURL = CFURLCopyAbsoluteURL(executableURL);
#if DEPLOYMENT_TARGET_WINDOWS
executablePath = CFURLCopyFileSystemPath(absURL, kCFURLWindowsPathStyle);
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
executablePath = CFURLCopyFileSystemPath(absURL, kCFURLPOSIXPathStyle);
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
CFRelease(absURL);
__CFSpinLock(&CFBundleExecutablePathLock);
// returns zero-ref dictionary under GC
static CFDictionaryRef _CFBundleGrokInfoDictFromFile(int fd, const void *bytes, CFIndex length, uint32_t offset, Boolean swapped, Boolean sixtyFour) {
- struct stat statBuf;
+ struct statinfo statBuf;
off_t fileLength = 0;
char *maploc = NULL;
const char *loc;
} else if (bytes < data && data + 41 <= bytes + length && 8 == CFSwapInt16HostToLittle(*((UInt16 *)(bytes + 8))) && 0x4b2c28c8 == CFSwapInt32HostToBig(*((UInt32 *)data)) && 0xc94c4e2c == CFSwapInt32HostToBig(*((UInt32 *)(data + 4)))) {
// AbiWord compressed mimetype odt
if (ext) *ext = "odt";
+ // almost certainly this should set i to 0 but I don't want to upset the apple cart now
+ } else if (bytes < data && data + 29 <= bytes + length && (0 == ustrncasecmp(data, "application/oebps-package+xml", 29))) {
+ // epub, official epub 3 mime type
+ if (ext) *ext = "epub";
+ i = 0;
+ } else if (bytes < data && data + 20 <= bytes + length && (0 == ustrncasecmp(data, "application/epub+zip", 20))) {
+ // epub, unofficial epub 2 mime type
+ if (ext) *ext = "epub";
+ i = 0;
}
return (i >= 0);
}
return ext;
}
-#if DEPLOYMENT_TARGET_WINDOWS
-// Windows isspace implementation limits the input chars to < 256 in the ASCII range. It will
-// assert in debug builds. This is annoying. We merrily grok chars > 256.
-static inline BOOL isspace(char c) {
- return (c == ' ' || c == '\t' || c == '\n' || c == '\r'|| c == '\v' || c == '\f');
-}
-#endif
-
// 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;
Boolean gotPath = FALSE;
char path[CFMaxPathSize];
gotPath = CFURLGetFileSystemRepresentation(url, true, (uint8_t *)path, CFMaxPathSize);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
- struct stat statBuf;
-#elif DEPLOYMENT_TARGET_WINDOWS
- struct _stat statBuf;
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
-#endif
+ struct statinfo statBuf;
if (gotPath && stat(path, &statBuf) == 0 && (statBuf.st_mode & S_IFMT) == S_IFREG && (fd = open(path, O_RDONLY | CF_OPENFLGS, 0777)) >= 0) {
length = read(fd, buffer, MAGIC_BYTES_TO_READ);
fileLength = statBuf.st_size;
CFErrorRef localError = NULL, *subError = (error ? &localError : NULL);
CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
- __CFSpinLock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_lock(&(bundle->_bundleLoadingLock));
if (!executableURL) bundle->_binaryType = __CFBundleNoBinary;
// make sure we know whether bundle is already loaded or not
#if defined(BINARY_SUPPORT_DLFCN)
if (executableURL) CFRelease(executableURL);
if (bundle->_isLoaded) {
- __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
// Remove from the scheduled unload set if we are there.
- __CFSpinLock(&CFBundleGlobalDataLock);
-#if defined(AVOID_WEAK_COLLECTIONS)
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
+#if AVOID_WEAK_COLLECTIONS
if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle);
#else /* AVOID_WEAK_COLLECTIONS */
if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle];
#endif /* AVOID_WEAK_COLLECTIONS */
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
return true;
}
// Unload bundles scheduled for unloading
if (!_scheduledBundlesAreUnloading) {
- __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
_CFBundleUnloadScheduledBundles();
- __CFSpinLock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_lock(&(bundle->_bundleLoadingLock));
}
if (bundle->_isLoaded) {
- __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
// Remove from the scheduled unload set if we are there.
- __CFSpinLock(&CFBundleGlobalDataLock);
-#if defined(AVOID_WEAK_COLLECTIONS)
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
+#if AVOID_WEAK_COLLECTIONS
if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle);
#else /* AVOID_WEAK_COLLECTIONS */
if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle];
#endif /* AVOID_WEAK_COLLECTIONS */
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
return true;
}
- __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
switch (bundle->_binaryType) {
#if defined(BINARY_SUPPORT_DLFCN)
#endif
CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
- __CFSpinLock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_lock(&(bundle->_bundleLoadingLock));
if (!executableURL) bundle->_binaryType = __CFBundleNoBinary;
// make sure we know whether bundle is already loaded or not
#if defined(BINARY_SUPPORT_DLFCN)
if (executableURL) CFRelease(executableURL);
if (bundle->_isLoaded) {
- __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
return true;
}
- __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
switch (bundle->_binaryType) {
#if defined(BINARY_SUPPORT_DLFCN)
if (!bundle->_isLoaded) return;
// Remove from the scheduled unload set if we are there.
- if (!_scheduledBundlesAreUnloading) __CFSpinLock(&CFBundleGlobalDataLock);
-#if defined(AVOID_WEAK_COLLECTIONS)
+ if (!_scheduledBundlesAreUnloading) pthread_mutex_lock(&CFBundleGlobalDataLock);
+#if AVOID_WEAK_COLLECTIONS
if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle);
#else /* AVOID_WEAK_COLLECTIONS */
if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle];
#endif /* AVOID_WEAK_COLLECTIONS */
- if (!_scheduledBundlesAreUnloading) __CFSpinUnlock(&CFBundleGlobalDataLock);
+ if (!_scheduledBundlesAreUnloading) pthread_mutex_unlock(&CFBundleGlobalDataLock);
// Give the plugIn code a chance to realize this...
_CFPlugInWillUnload(bundle);
- __CFSpinLock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_lock(&(bundle->_bundleLoadingLock));
if (!bundle->_isLoaded) {
- __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
return;
}
- __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
switch (bundle->_binaryType) {
#if defined(BINARY_SUPPORT_DYLD)
}
}
-#if defined(AVOID_WEAK_COLLECTIONS)
+#if AVOID_WEAK_COLLECTIONS
__private_extern__ void _CFBundleScheduleForUnloading(CFBundleRef bundle) {
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
if (!_bundlesToUnload) {
CFSetCallBacks nonRetainingCallbacks = kCFTypeSetCallBacks;
nonRetainingCallbacks.retain = NULL;
_bundlesToUnload = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &nonRetainingCallbacks);
}
CFSetAddValue(_bundlesToUnload, bundle);
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
}
__private_extern__ void _CFBundleUnscheduleForUnloading(CFBundleRef bundle) {
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle);
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
}
__private_extern__ void _CFBundleUnloadScheduledBundles(void) {
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
if (_bundlesToUnload) {
CFIndex i, c = CFSetGetCount(_bundlesToUnload);
if (c > 0) {
CFAllocatorDeallocate(kCFAllocatorSystemDefault, unloadThese);
}
}
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
}
#else /* AVOID_WEAK_COLLECTIONS */
__private_extern__ void _CFBundleScheduleForUnloading(CFBundleRef bundle) {
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
if (!_bundlesToUnload) _bundlesToUnload = [[__CFHashTable alloc] initWithOptions:CFPointerFunctionsZeroingWeakMemory capacity:0];
[_bundlesToUnload addObject:(id)bundle];
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
}
__private_extern__ void _CFBundleUnscheduleForUnloading(CFBundleRef bundle) {
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle];
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
}
__private_extern__ void _CFBundleUnloadScheduledBundles(void) {
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
if (_bundlesToUnload && [_bundlesToUnload count] > 0) {
CFIndex i, c;
CFMutableArrayRef unloadThese = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
}
CFRelease(unloadThese);
}
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
}
#endif /* AVOID_WEAK_COLLECTIONS */
//If 'permissive' is set, we will maintain the historical behavior of returning frameworks with names that don't match, and frameworks for executables in Resources/
static CFURLRef __CFBundleCopyFrameworkURLForExecutablePath(CFStringRef executablePath, Boolean permissive) {
// MF:!!! Implement me. We need to be able to find the bundle from the exe, dealing with old vs. new as well as the Executables dir business on Windows.
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#elif DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_WINDOWS
UniChar executablesToFrameworksPathBuff[] = {'.', '.', '\\', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
UniChar executablesToPrivateFrameworksPathBuff[] = {'.', '.', '\\', 'P', 'r', 'i', 'v', 'a', 't', 'e', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
UniChar frameworksExtension[] = {'f', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k'};
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
UniChar pathBuff[CFMaxPathSize] = {0};
UniChar nameBuff[CFMaxPathSize] = {0};
}
}
}
-
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
// * Finally check the executable inside the framework case.
if (!bundleURL) {
createdBundle = true;
}
if (bundle) {
- __CFSpinLock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_lock(&(bundle->_bundleLoadingLock));
if (!bundle->_isLoaded) {
// make sure that these bundles listed as loaded, and mark them frameworks (we probably can't see anything else here, and we cannot unload them)
#if defined(BINARY_SUPPORT_DLFCN)
#endif /* LOG_BUNDLE_LOAD */
bundle->_isLoaded = true;
}
- __CFSpinUnlock(&(bundle->_bundleLoadingLock));
+ pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
if (createdBundle) {
// Perform delayed final processing steps.
// This must be done after _isLoaded has been set, for security reasons (3624341).
- _CFBundleCheckWorkarounds(bundle);
if (_CFBundleNeedsInitPlugIn(bundle)) {
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
_CFBundleInitPlugIn(bundle);
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
}
} else {
// Release the bundle if we did not create it here
CFArrayRef CFBundleGetAllBundles(void) {
// To answer this properly, we have to have created the static bundles!
-#if !defined(AVOID_WEAK_COLLECTIONS)
+#if !AVOID_WEAK_COLLECTIONS
static CFMutableArrayRef externalAllBundles = NULL;
#endif /* AVOID_WEAK_COLLECTIONS */
CFArrayRef bundles;
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
_CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
-#if defined(AVOID_WEAK_COLLECTIONS)
+#if AVOID_WEAK_COLLECTIONS
bundles = _allBundles;
#else /* AVOID_WEAK_COLLECTIONS */
if (!externalAllBundles) {
for (id value in _allBundles) CFArrayAppendValue(externalAllBundles, value);
bundles = externalAllBundles;
#endif /* AVOID_WEAK_COLLECTIONS */
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
return bundles;
}
CF_EXPORT CFArrayRef _CFBundleCopyAllBundles(void) {
// To answer this properly, we have to have created the static bundles!
- __CFSpinLock(&CFBundleGlobalDataLock);
+ pthread_mutex_lock(&CFBundleGlobalDataLock);
_CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
-#if defined(AVOID_WEAK_COLLECTIONS)
+#if AVOID_WEAK_COLLECTIONS
CFArrayRef bundles = CFArrayCreateCopy(kCFAllocatorSystemDefault, _allBundles);
#else /* AVOID_WEAK_COLLECTIONS */
CFMutableArrayRef bundles = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
for (id value in _allBundles) CFArrayAppendValue(bundles, value);
#endif /* AVOID_WEAK_COLLECTIONS */
- __CFSpinUnlock(&CFBundleGlobalDataLock);
+ pthread_mutex_unlock(&CFBundleGlobalDataLock);
return bundles;
}
return bundle->_version;
}
+static void __addPlatformAndProductNamesToKeys(const void *value, void *context) {
+ CFMutableSetRef newKeys = (CFMutableSetRef)context;
+ CFStringRef key = (CFStringRef)value;
+ CFStringRef firstPartOfKey = NULL;
+ CFStringRef restOfKey = NULL;
+
+ // Find the first ':'
+ CFRange range;
+ Boolean success = CFStringFindWithOptions(key, CFSTR(":"), CFRangeMake(0, CFStringGetLength(key)), 0, &range);
+ if (success) {
+ firstPartOfKey = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, key, CFRangeMake(0, range.location));
+ restOfKey = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, key, CFRangeMake(range.location + 1, CFStringGetLength(key) - range.location - 1));
+ } else {
+ firstPartOfKey = (CFStringRef)CFRetain(key);
+ }
+
+ // only apply product and platform to top-level key
+ CFStringRef newKeyWithPlatform = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@-%@%@%@"), firstPartOfKey, _CFGetPlatformName(), restOfKey ? CFSTR(":") : CFSTR(""), restOfKey ? restOfKey : CFSTR(""));
+ CFStringRef newKeyWithProduct = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@~%@%@%@"), firstPartOfKey, _CFGetProductName(), restOfKey ? CFSTR(":") : CFSTR(""), restOfKey ? restOfKey : CFSTR(""));
+ CFStringRef newKeyWithProductAndPlatform = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@-%@~%@%@%@"), firstPartOfKey, _CFGetPlatformName(), _CFGetProductName(), restOfKey ? CFSTR(":") : CFSTR(""), restOfKey ? restOfKey : CFSTR(""));
+
+ CFSetAddValue(newKeys, key);
+ CFSetAddValue(newKeys, newKeyWithPlatform);
+ CFSetAddValue(newKeys, newKeyWithProduct);
+ CFSetAddValue(newKeys, newKeyWithProductAndPlatform);
+
+ if (firstPartOfKey) CFRelease(firstPartOfKey);
+ if (restOfKey) CFRelease(restOfKey);
+ CFRelease(newKeyWithPlatform);
+ CFRelease(newKeyWithProduct);
+ CFRelease(newKeyWithProductAndPlatform);
+}
+
+// from CFUtilities.c
+__private_extern__ Boolean _CFReadMappedFromFile(CFStringRef path, Boolean map, Boolean uncached, void **outBytes, CFIndex *outLength, CFErrorRef *errorPtr);
+
+// implementation of below functions - takes URL as parameter
+static CFPropertyListRef _CFBundleCreateFilteredInfoPlistWithURL(CFURLRef infoPlistURL, CFSetRef keyPaths, _CFBundleFilteredPlistOptions options) {
+ CFPropertyListRef result = NULL;
+
+ if (!infoPlistURL) return CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ CFURLRef absoluteURL = CFURLCopyAbsoluteURL(infoPlistURL);
+ CFStringRef filePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
+ CFRelease(absoluteURL);
+
+ if (!filePath) return CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ void *bytes = NULL;
+ CFIndex length = 0;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
+ Boolean mapped = options & _CFBundleFilteredPlistMemoryMapped ? true : false;
+#else
+ Boolean mapped = false;
+#endif
+ Boolean success = _CFReadMappedFromFile(filePath, mapped, false, &bytes, &length, NULL);
+ CFRelease(filePath);
+ if (!success) return CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ CFDataRef infoPlistData = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, (const UInt8 *)bytes, length, kCFAllocatorNull);
+ // We need to include all possible variants of the platform/product combo as possible keys.
+ CFMutableSetRef newKeyPaths = CFSetCreateMutable(kCFAllocatorSystemDefault, CFSetGetCount(keyPaths), &kCFTypeSetCallBacks);
+ CFSetApplyFunction(keyPaths, __addPlatformAndProductNamesToKeys, newKeyPaths);
+
+ success = _CFPropertyListCreateFiltered(kCFAllocatorSystemDefault, infoPlistData, kCFPropertyListMutableContainers, newKeyPaths, &result, NULL);
+
+ if (!success) {
+ result = CFDictionaryCreate(kCFAllocatorSystemDefault, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ } else {
+ _processInfoDictionary((CFMutableDictionaryRef)result, _CFGetPlatformName(), _CFGetProductName());
+ }
+
+ CFRelease(newKeyPaths);
+ CFRelease(infoPlistData);
+ if (mapped) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
+ munmap(bytes, length);
+#endif
+ } else {
+ free(bytes);
+ }
+
+ return result;
+}
+
+// Returns a subset of the bundle's property list, only including the keyPaths in the CFSet. If the top level object is not a dictionary, you will get back an empty dictionary as the result. If the Info.plist does not exist or could not be parsed, you will get back an empty dictionary.
+CF_EXPORT CFPropertyListRef _CFBundleCreateFilteredInfoPlist(CFBundleRef bundle, CFSetRef keyPaths, _CFBundleFilteredPlistOptions options) {
+ CFURLRef infoPlistURL = _CFBundleCopyInfoPlistURL(bundle);
+ CFPropertyListRef result = _CFBundleCreateFilteredInfoPlistWithURL(infoPlistURL, keyPaths, options);
+ if (infoPlistURL) CFRelease(infoPlistURL);
+ return result;
+}
+
+CF_EXPORT CFPropertyListRef _CFBundleCreateFilteredLocalizedInfoPlist(CFBundleRef bundle, CFSetRef keyPaths, CFStringRef localizationName, _CFBundleFilteredPlistOptions options) {
+ CFURLRef infoPlistURL = CFBundleCopyResourceURLForLocalization(bundle, _CFBundleLocalInfoName, _CFBundleStringTableType, NULL, localizationName);
+ CFPropertyListRef result = _CFBundleCreateFilteredInfoPlistWithURL(infoPlistURL, keyPaths, options);
+ if (infoPlistURL) CFRelease(infoPlistURL);
+ return result;
+}
+
CF_EXPORT CFURLRef _CFBundleCopyInfoPlistURL(CFBundleRef bundle) {
CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
CFURLRef url = (CFURLRef)CFDictionaryGetValue(infoDict, _kCFBundleInfoPlistURLKey);
if (!url) url = (CFURLRef)CFDictionaryGetValue(infoDict, _kCFBundleRawInfoPlistURLKey);
return (url ? (CFURLRef)CFRetain(url) : NULL);
}
-
+
CF_EXPORT CFURLRef _CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle) {
return CFBundleCopyPrivateFrameworksURL(bundle);
}
}
#if defined(BINARY_SUPPORT_DYLD)
if (hasSuitableArch) {
- uint32_t mainFlags = 0, bundleFlags = 0;
+ uint32_t mainFlags = 0;
if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL, &mainFlags) && (mainFlags & 0x2) != 0) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+ uint32_t bundleFlags = 0;
if (_CFBundleGetObjCImageInfo(bundle, NULL, &bundleFlags) && (bundleFlags & 0x2) == 0) hasRuntimeMismatch = true;
+#endif
}
}
#endif /* BINARY_SUPPORT_DYLD */
/* 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;
+}
-static void _CFBundleCheckWorkarounds(CFBundleRef bundle) {
+// 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;
}
+
+
+
+
*/
/* CFBundle.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFBUNDLE__)
CF_EXPORT
CFURLRef CFBundleCopyExecutableURL(CFBundleRef bundle);
-#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
enum {
kCFBundleExecutableArchitectureI386 = 0x00000007,
kCFBundleExecutableArchitecturePPC = 0x00000012,
kCFBundleExecutableArchitectureX86_64 = 0x01000007,
kCFBundleExecutableArchitecturePPC64 = 0x01000012
-};
-#endif /* MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED */
+} CF_ENUM_AVAILABLE(10_5, 2_0);
CF_EXPORT
CFArrayRef CFBundleCopyExecutableArchitectures(CFBundleRef bundle) CF_AVAILABLE(10_5, 2_0);
*/
/* CFBundlePriv.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFBUNDLEPRIV__)
*/
/* CFBundle_BinaryTypes.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFBUNDLE_BINARYTYPES__)
#define BINARY_SUPPORT_DYLD 1
#define BINARY_SUPPORT_DLFCN 1
#define USE_DYLD_PRIV 1
-#elif DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#define BINARY_SUPPORT_DYLD 1
#define BINARY_SUPPORT_DLFCN 1
-#if !defined(TARGET_IPHONE_SIMULATOR)
#define USE_DYLD_PRIV 1
-#endif
#elif DEPLOYMENT_TARGET_WINDOWS
#define BINARY_SUPPORT_DLL 1
#else
*/
/* CFBundle_Internal.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFBUNDLE_INTERNAL__)
#define __kCFLogBundle 3
#define __kCFLogPlugIn 3
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#define PLATFORM_PATH_STYLE kCFURLPOSIXPathStyle
-#elif DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_WINDOWS
#define PLATFORM_PATH_STYLE kCFURLWindowsPathStyle
#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
+#define PLATFORM_PATH_STYLE kCFURLPOSIXPathStyle
#endif
#define CFBundleExecutableNotFoundError 4
#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
+
typedef struct __CFResourceData {
CFMutableDictionaryRef _stringTableCache;
Boolean _executableLacksResourceFork;
extern Boolean _CFBundleCouldBeBundle(CFURLRef url);
extern CFURLRef _CFBundleCopyResourceForkURLMayBeLocal(CFBundleRef bundle, Boolean mayBeLocal);
extern CFDictionaryRef _CFBundleCopyInfoDictionaryInResourceForkWithAllocator(CFAllocatorRef alloc, CFURLRef url);
-extern CFStringRef _CFBundleCopyBundleDevelopmentRegionFromVersResource(CFBundleRef bundle);
+#if DEPLOYMENT_TARGET_MACOSX
+__private_extern__ CFStringRef _CFBundleCopyBundleDevelopmentRegionFromVersResource(CFBundleRef bundle);
+#endif
extern CFDictionaryRef _CFBundleCopyInfoDictionaryInExecutable(CFURLRef url);
extern CFArrayRef _CFBundleCopyArchitecturesForExecutable(CFURLRef url);
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);
#if defined(BINARY_SUPPORT_DYLD)
// DYLD API
extern void _CFPlugInAddPlugInInstance(CFPlugInRef plugIn);
extern void _CFPlugInRemovePlugInInstance(CFPlugInRef plugIn);
-extern void _CFPlugInAddFactory(CFPlugInRef plugIn, _CFPFactory *factory);
-extern void _CFPlugInRemoveFactory(CFPlugInRef plugIn, _CFPFactory *factory);
+extern void _CFPlugInAddFactory(CFPlugInRef plugIn, _CFPFactoryRef factory);
+extern void _CFPlugInRemoveFactory(CFPlugInRef plugIn, _CFPFactoryRef factory);
/* Strings for parsing bundle structure */
#define _CFBundleLprojExtension CFSTR("lproj")
#define _CFBundleLprojExtensionWithDot CFSTR(".lproj")
+#define _CFBundleDot CFSTR(".")
+#define _CFBundleAllFiles CFSTR("_CFBAF_")
+#define _CFBundleTypeIndicator CFSTR("_CFBT_")
+// This directory contains resources (especially nibs) that may look up localized resources or may fall back to the development language resources
+#define _CFBundleBaseDirectory CFSTR("Base")
#define _CFBundleMacOSXPlatformName CFSTR("macos")
#define _CFBundleAlternateMacOSXPlatformName CFSTR("macosx")
#define _CFBundleLocalizedResourceForkFileName CFSTR("Localized")
-#if DEPLOYMENT_TARGET_WINDOWS
#define _CFBundleWindowsResourceDirectoryExtension CFSTR("resources")
-#endif
/* Old platform names (no longer used) */
#define _CFBundleMacOSXPlatformName_OLD CFSTR("macintosh")
*/
/* CFBundle_Resources.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
- Responsibility: David Smith
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
+ Responsibility: Tony Parker
*/
-#if DEPLOYMENT_TARGET_MACOSX
-#define READ_DIRECTORIES 1
-#elif DEPLOYMENT_TARGET_EMBEDDED
-#define READ_DIRECTORIES 1
-#elif DEPLOYMENT_TARGET_WINDOWS
-#define READ_DIRECTORIES 0
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
-#endif
-
#define READ_DIRECTORIES_CACHE_CAPACITY 128
#include "CFBundle_Internal.h"
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
+#include <unistd.h>
#include <sys/sysctl.h>
+#include <sys/stat.h>
+#include <dirent.h>
#endif
#if DEPLOYMENT_TARGET_MACOSX
-#include <unistd.h>
-#elif DEPLOYMENT_TARGET_EMBEDDED
-#include <unistd.h>
-#elif DEPLOYMENT_TARGET_WINDOWS
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
+
#endif
-#if READ_DIRECTORIES
-#include <dirent.h>
-#endif /* READ_DIRECTORIES */
+#if DEPLOYMENT_TARGET_WINDOWS
+#include <io.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#define close _close
+#define write _write
+#define read _read
+#define open _NS_open
+#define stat _NS_stat
+#define fstat _fstat
+#define mkdir(a,b) _NS_mkdir(a)
+#define rmdir _NS_rmdir
+#define unlink _NS_unlink
+
+#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));
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 Windows
-// This is here to make sure it gets updated when _CFGetPlatformName does
+// 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" };
-// This is here to make sure it gets updated when _CFGetProductName does
#define _CFBundleNumberOfProducts 3
static CFStringRef _CFBundleSupportedProducts[_CFBundleNumberOfProducts] = { NULL, NULL, NULL };
static const char *_CFBundleSupportedProductStrings[_CFBundleNumberOfProducts] = { "iphone", "ipod", "ipad" };
static CFStringRef _CFBundleSupportediPhoneOSPlatformProducts[_CFBundleNumberOfiPhoneOSPlatformProducts] = { NULL, NULL, NULL };
static const char *_CFBundleSupportediPhoneOSPlatformProductStrings[_CFBundleNumberOfiPhoneOSPlatformProducts] = { "iphone", "ipod", "ipad" };
-void _CFBundleResourcesInitialize() {
+__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) {
// shouldn't be screwing around with this value casually.
}
-CFStringRef _CFGetProductName(void) {
-#if DEPLOYMENT_TARGET_EMBEDDED
+CF_EXPORT CFStringRef _CFGetProductName(void) {
+#if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (!platform) {
char buffer[256];
memset(buffer, 0, sizeof(buffer));
}
// All new-style bundles will have these extensions.
-__private_extern__ CFStringRef _CFGetPlatformName(void) {
+CF_EXPORT CFStringRef _CFGetPlatformName(void) {
#if DEPLOYMENT_TARGET_MACOSX
return _CFBundleMacOSXPlatformName;
-#elif DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
return _CFBundleiPhoneOSPlatformName;
#elif DEPLOYMENT_TARGET_WINDOWS
return _CFBundleWindowsPlatformName;
#endif
}
-__private_extern__ CFStringRef _CFGetAlternatePlatformName(void) {
+CF_EXPORT CFStringRef _CFGetAlternatePlatformName(void) {
#if DEPLOYMENT_TARGET_MACOSX
return _CFBundleAlternateMacOSXPlatformName;
-#elif DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
return _CFBundleMacOSXPlatformName;
#elif DEPLOYMENT_TARGET_WINDOWS
return CFSTR("");
#endif
}
-static CFSpinLock_t CFBundleResourceGlobalDataLock = CFSpinLockInit;
static UniChar *_AppSupportUniChars1 = NULL;
static CFIndex _AppSupportLen1 = 0;
static UniChar *_AppSupportUniChars2 = 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];
CFStringRef lprojStr = _CFBundleLprojExtension;
CFStringRef globalResourcesStr = _CFBundleNonLocalizedResourcesDirectoryName;
CFStringRef infoExtensionStr = _CFBundleInfoExtension;
+ CFStringRef baseStr = _CFBundleBaseDirectory;
_AppSupportLen1 = CFStringGetLength(appSupportStr1);
_AppSupportLen2 = CFStringGetLength(appSupportStr2);
_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), 0);
+ _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;
_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 (_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 (_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) {
- __CFSpinLock(&CFBundleResourceGlobalDataLock);
- if (!_AppSupportUniChars1) _CFBundleInitStaticUniCharBuffers();
- __CFSpinUnlock(&CFBundleResourceGlobalDataLock);
+ static dispatch_once_t once = 0;
+ dispatch_once(&once, ^{
+ _CFBundleInitStaticUniCharBuffers();
+ });
}
-#if READ_DIRECTORIES
-
-static CFMutableDictionaryRef contentsCache = NULL;
-static CFMutableDictionaryRef directoryContentsCache = NULL;
-static CFMutableDictionaryRef unknownContentsCache = NULL;
+static CFSpinLock_t _cacheLock = CFSpinLockInit;
+static CFMutableDictionaryRef _contentsCache = NULL;
+static CFMutableDictionaryRef _directoryContentsCache = NULL;
+static CFMutableDictionaryRef _unknownContentsCache = NULL;
typedef enum {
_CFBundleAllContents = 0,
static CFArrayRef _CFBundleCopySortedDirectoryContentsAtPath(CFStringRef path, _CFBundleDirectoryContentsType contentsType) {
CFArrayRef result = NULL;
- __CFSpinLock(&CFBundleResourceGlobalDataLock);
+ __CFSpinLock(&_cacheLock);
if (contentsType == _CFBundleUnknownContents) {
- if (unknownContentsCache) result = (CFMutableArrayRef)CFDictionaryGetValue(unknownContentsCache, path);
+ if (_unknownContentsCache) result = (CFMutableArrayRef)CFDictionaryGetValue(_unknownContentsCache, path);
} else if (contentsType == _CFBundleDirectoryContents) {
- if (directoryContentsCache) result = (CFMutableArrayRef)CFDictionaryGetValue(directoryContentsCache, path);
+ if (_directoryContentsCache) result = (CFMutableArrayRef)CFDictionaryGetValue(_directoryContentsCache, path);
} else {
- if (contentsCache) result = (CFMutableArrayRef)CFDictionaryGetValue(contentsCache, path);
+ if (_contentsCache) result = (CFMutableArrayRef)CFDictionaryGetValue(_contentsCache, path);
}
if (result) CFRetain(result);
- __CFSpinUnlock(&CFBundleResourceGlobalDataLock);
+ __CFSpinUnlock(&_cacheLock);
if (!result) {
Boolean tryToOpen = false, allDots = true;
char cpathBuff[CFMaxPathSize];
CFIndex cpathLen = 0, idx, lastSlashIdx = 0;
- DIR *dirp = NULL;
- struct dirent *dent;
CFMutableArrayRef contents = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks), directoryContents = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks), unknownContents = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
CFStringRef dirName, name;
// First see whether we already know that the directory doesn't exist
for (idx = cpathLen; lastSlashIdx == 0 && idx-- > 0;) {
- if (cpathBuff[idx] == '/') lastSlashIdx = idx;
+ if (cpathBuff[idx] == PATH_SEP) lastSlashIdx = idx;
else if (cpathBuff[idx] != '.') allDots = false;
}
if (lastSlashIdx > 0 && lastSlashIdx + 1 < cpathLen && !allDots) {
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
+ // ??? we might like to use _directoryContentsCache rather than _contentsCache here, but we cannot unless we resolve DT_LNKs below
CFArrayRef dirDirContents = NULL;
- __CFSpinLock(&CFBundleResourceGlobalDataLock);
- if (contentsCache) dirDirContents = (CFArrayRef)CFDictionaryGetValue(contentsCache, dirName);
+ __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, CFArrayGetValueAtIndex(dirDirContents, dirDirIdx), kCFCompareCaseInsensitive)) foundIt = true;
+ for (dirDirIdx = 0; !foundIt && dirDirIdx < dirDirLength; dirDirIdx++) if (kCFCompareEqualTo == CFStringCompare(name, (CFStringRef)CFArrayGetValueAtIndex(dirDirContents, dirDirIdx), kCFCompareCaseInsensitive)) foundIt = true;
if (!foundIt) tryToOpen = false;
}
- __CFSpinUnlock(&CFBundleResourceGlobalDataLock);
+ __CFSpinUnlock(&_cacheLock);
CFRelease(name);
}
CFRelease(dirName);
}
- cpathBuff[lastSlashIdx] = '/';
+ 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;
}
(void)closedir(dirp);
}
+#endif
_CFArraySortValues(contents, (CFComparatorFunction)CFStringCompare, NULL);
_CFArraySortValues(directoryContents, (CFComparatorFunction)CFStringCompare, NULL);
_CFArraySortValues(unknownContents, (CFComparatorFunction)CFStringCompare, NULL);
- __CFSpinLock(&CFBundleResourceGlobalDataLock);
- if (!contentsCache) contentsCache = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, READ_DIRECTORIES_CACHE_CAPACITY, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- if (READ_DIRECTORIES_CACHE_CAPACITY <= CFDictionaryGetCount(contentsCache)) CFDictionaryRemoveAllValues(contentsCache);
- CFDictionaryAddValue(contentsCache, path, contents);
+ __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 (!_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 (!_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 = CFRetain(unknownContents);
+ result = (CFArrayRef)CFRetain(unknownContents);
} else if (contentsType == _CFBundleDirectoryContents) {
- result = CFRetain(directoryContents);
+ result = (CFArrayRef)CFRetain(directoryContents);
} else {
- result = CFRetain(contents);
+ result = (CFArrayRef)CFRetain(contents);
}
CFRelease(contents);
CFRelease(directoryContents);
CFRelease(unknownContents);
- __CFSpinUnlock(&CFBundleResourceGlobalDataLock);
+ __CFSpinUnlock(&_cacheLock);
}
return result;
}
static void _CFBundleFlushContentsCaches(void) {
- __CFSpinLock(&CFBundleResourceGlobalDataLock);
- if (contentsCache) CFDictionaryRemoveAllValues(contentsCache);
- if (directoryContentsCache) CFDictionaryRemoveAllValues(directoryContentsCache);
- if (unknownContentsCache) CFDictionaryRemoveAllValues(unknownContentsCache);
- __CFSpinUnlock(&CFBundleResourceGlobalDataLock);
+ __CFSpinLock(&_cacheLock);
+ if (_contentsCache) CFDictionaryRemoveAllValues(_contentsCache);
+ if (_directoryContentsCache) CFDictionaryRemoveAllValues(_directoryContentsCache);
+ if (_unknownContentsCache) CFDictionaryRemoveAllValues(_unknownContentsCache);
+ __CFSpinUnlock(&_cacheLock);
}
static void _CFBundleFlushContentsCacheForPath(CFMutableDictionaryRef cache, CFStringRef path) {
}
static void _CFBundleFlushContentsCachesForPath(CFStringRef path) {
- __CFSpinLock(&CFBundleResourceGlobalDataLock);
- if (contentsCache) _CFBundleFlushContentsCacheForPath(contentsCache, path);
- if (directoryContentsCache) _CFBundleFlushContentsCacheForPath(directoryContentsCache, path);
- if (unknownContentsCache) _CFBundleFlushContentsCacheForPath(unknownContentsCache, path);
- __CFSpinUnlock(&CFBundleResourceGlobalDataLock);
+ __CFSpinLock(&_cacheLock);
+ if (_contentsCache) _CFBundleFlushContentsCacheForPath(_contentsCache, path);
+ if (_directoryContentsCache) _CFBundleFlushContentsCacheForPath(_directoryContentsCache, path);
+ if (_unknownContentsCache) _CFBundleFlushContentsCacheForPath(_unknownContentsCache, path);
+ __CFSpinUnlock(&_cacheLock);
}
-#endif /* READ_DIRECTORIES */
-
CF_EXPORT void _CFBundleFlushCachesForURL(CFURLRef url) {
-#if READ_DIRECTORIES
CFURLRef absoluteURL = CFURLCopyAbsoluteURL(url);
CFStringRef path = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
_CFBundleFlushContentsCachesForPath(path);
CFRelease(path);
CFRelease(absoluteURL);
-#endif /* READ_DIRECTORIES */
}
CF_EXPORT void _CFBundleFlushCaches(void) {
-#if READ_DIRECTORIES
_CFBundleFlushContentsCaches();
-#endif /* READ_DIRECTORIES */
}
static inline Boolean _CFIsResourceCommon(char *path, Boolean *isDir) {
return _CFIsResourceCommon(pathBuf, isDir);
}
-#if READ_DIRECTORIES
+__private_extern__ void _CFBundleSetResourceDir(UniChar *buffer, CFIndex *currLen, CFIndex maxLen, uint8_t version){
+ if (1 == version) {
+ _CFAppendPathComponent(buffer, currLen, maxLen, _AppSupportUniChars1, _AppSupportLen1);
+ } 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;
CFStringSetExternalCharactersNoCopy(tmpString, nameUniChars, nameLen, nameLen);
CFStringReplaceAll(cheapStr, tmpString);
for (i = 0; i < contentsRange.length; i++) {
- CFStringRef content = CFArrayGetValueAtIndex(contents, i);
+ CFStringRef content = (CFStringRef)CFArrayGetValueAtIndex(contents, i);
if (CFStringHasPrefix(content, cheapStr)) {
//fprintf(stderr, "found ");CFShow(content);
for (j = 0; j < numResTypes; j++) {
- CFStringRef resType = CFArrayGetValueAtIndex(resTypes, j);
+ CFStringRef resType = (CFStringRef)CFArrayGetValueAtIndex(resTypes, j);
if (!CFArrayContainsValue(result, resultRange, resType) && CFStringHasSuffix(content, resType)) {
CFArrayAppendValue(result, resType);
resultRange.length = CFArrayGetCount(result);
CFRelease(contents);
return result;
}
-#endif /* READ_DIRECTORIES */
-#if DEPLOYMENT_TARGET_EMBEDDED
+#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.
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
+#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.
// URLs for found resources get added to result.
CFIndex savedPathLen;
Boolean appendSucceeded = true, platformGenericFound = false, platformSpecificFound = false, platformGenericIsDir = false, platformSpecificIsDir = false;
-#if READ_DIRECTORIES
Boolean platformGenericIsUnknown = false, platformSpecificIsUnknown = false;
-#endif
CFStringRef platformGenericStr = NULL;
-#if READ_DIRECTORIES
CFIndex dirPathLen = pathLen;
CFArrayRef contents, directoryContents, unknownContents;
CFRange contentsRange, directoryContentsRange, unknownContentsRange;
directoryContentsRange = CFRangeMake(0, CFArrayGetCount(directoryContents));
unknownContents = _CFBundleCopySortedDirectoryContentsAtPath(cheapStr, _CFBundleUnknownContents);
unknownContentsRange = CFRangeMake(0, CFArrayGetCount(unknownContents));
-#endif /* READ_DIRECTORIES */
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) {
-#if READ_DIRECTORIES
CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars + dirPathLen + 1, pathLen - dirPathLen - 1, pathLen - dirPathLen - 1);
CFStringReplaceAll(cheapStr, tmpString);
platformGenericFound = _CFBundleSortedArrayContains(contents, cheapStr);
(void)_CFIsResourceAtPath(cheapStr, &platformGenericIsDir);
//if (platformGenericIsDir) fprintf(stderr, "a directory after all\n"); else fprintf(stderr, "not a directory after all\n");
}
-#else /* READ_DIRECTORIES */
- CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen);
- CFStringReplaceAll(cheapStr, tmpString);
- platformGenericFound = _CFIsResourceAtPath(cheapStr, &platformGenericIsDir);
-#endif /* READ_DIRECTORIES */
}
// Check for platform specific.
pathLen += _PlatformLen;
if (appendSucceeded && typeLen > 0) appendSucceeded = _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, typeUniChars, typeLen);
if (appendSucceeded) {
-#if READ_DIRECTORIES
CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars + dirPathLen + 1, pathLen - dirPathLen - 1, pathLen - dirPathLen - 1);
CFStringReplaceAll(cheapStr, tmpString);
platformSpecificFound = _CFBundleSortedArrayContains(contents, cheapStr);
(void)_CFIsResourceAtPath(cheapStr, &platformSpecificIsDir);
//if (platformSpecificIsDir) fprintf(stderr, "a directory after all\n"); else fprintf(stderr, "not a directory after all\n");
}
-#else /* READ_DIRECTORIES */
- CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen);
- CFStringReplaceAll(cheapStr, tmpString);
- platformSpecificFound = _CFIsResourceAtPath(cheapStr, &platformSpecificIsDir);
-#endif /* READ_DIRECTORIES */
}
}
}
CFRelease(url);
}
if (platformGenericStr) CFRelease(platformGenericStr);
-#if READ_DIRECTORIES
CFRelease(contents);
CFRelease(directoryContents);
CFRelease(unknownContents);
-#endif /* READ_DIRECTORIES */
#endif
}
-#if READ_DIRECTORIES
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.
// scan directory contents for matches against predicate
for (int i = 0; i < contentsRange.length; i++) {
- CFStringRef candidateFilename = CFArrayGetValueAtIndex(contents, 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
CFRelease(directoryContents);
CFRelease(unknownContents);
}
-#endif
+
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) {
-#if READ_DIRECTORIES
_CFSearchBundleDirectoryWithPredicate(alloc, result, workingUniChars, workingLen, predicate, cheapStr, tmpString, stopLooking, version);
return;
-#else
- CFLog(kCFLogLevelCritical, CFSTR("_CFFindBundleResourcesInRawDir: predicate blocks are not supported on this platform"));
- HALT;
-#endif
}
if (nameLen > 0) {
// If we have a resName, just call the search API. We may have to loop over the resTypes.
CFArrayRef subResTypes = resTypes;
Boolean releaseSubResTypes = false;
CFIndex i, c = CFArrayGetCount(resTypes);
-#if READ_DIRECTORIES
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
c = CFArrayGetCount(subResTypes);
releaseSubResTypes = true;
}
-#endif /* READ_DIRECTORIES */
for (i = 0; i < c; i++) {
CFStringRef curType = (CFStringRef)CFArrayGetValueAtIndex(subResTypes, i);
CFIndex typeLen = CFStringGetLength(curType);
}
}
+
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
// 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 local resources.
+ // 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 langCount = (searchLanguages ? CFArrayGetCount(searchLanguages) : 0);
- // MF:??? OK to hard-wire this length?
- UniChar curLangUniChars[255];
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;
+ }
+ }
+ }
- for (CFIndex langIndex = 0; langIndex < langCount; langIndex++) {
+ // 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 = CFStringGetLength(curLangStr);
- if (curLangLen > 255) curLangLen = 255;
+ CFIndex curLangLen = MIN(CFStringGetLength(curLangStr), 255);
CFStringGetCharacters(curLangStr, CFRangeMake(0, curLangLen), curLangUniChars);
savedWorkingLen = workingLen;
if (!_CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, curLangUniChars, curLangLen)) {
}
}
-extern void _CFStrSetDesiredCapacity(CFMutableStringRef str, CFIndex len);
-
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);
if ((workingLen = CFStringGetLength(basePath)) > 0) CFStringGetCharacters(basePath, CFRangeMake(0, workingLen), workingUniChars);
savedWorkingLen = workingLen;
- if (1 == version) {
- _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _AppSupportUniChars1, _AppSupportLen1);
- } else if (2 == version) {
- _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _AppSupportUniChars2, _AppSupportLen2);
- }
- if (0 == version || 1 == version || 2 == version) _CFAppendPathComponent(workingUniChars, &workingLen, CFMaxPathSize, _ResourcesUniChars, _ResourcesLen);
+ _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);
_CFFindBundleResourcesInResourcesDir(kCFAllocatorSystemDefault, workingUniChars, workingLen, subDirUniChars, subDirLen, searchLanguages, nameUniChars, nameLen, resTypes, limit, predicate, version, cheapStr, tmpString, result);
- // drd: This unfortunate hack is still necessary because of installer packages and Spotlight importers
- if (CFArrayGetCount(result) == 0 && (0 == version || (2 == version && CFEqual(CFSTR("/Library/Spotlight"), basePath)))) {
- // Try looking directly in the bundle path
- workingLen = savedWorkingLen;
- _CFFindBundleResourcesInResourcesDir(kCFAllocatorSystemDefault, workingUniChars, workingLen, subDirUniChars, subDirLen, searchLanguages, nameUniChars, nameLen, resTypes, limit, predicate, version, cheapStr, tmpString, result);
- }
-
CFRelease(cheapStr);
CFRelease(tmpString);
CFAllocatorDeallocate(kCFAllocatorSystemDefault, nameUniChars);
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;
+ 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);
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?
if (types) CFRelease(types);
return array;
+#endif
}
CF_EXPORT CFURLRef _CFBundleCopyResourceURLForLanguage(CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language) {
}
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 (types) CFRelease(types);
if (languages) CFRelease(languages);
return result;
+#endif
}
CF_EXPORT CFArrayRef _CFBundleCopyResourceURLsOfTypeForLanguage(CFBundleRef bundle, CFStringRef resourceType, CFStringRef subDirName, CFStringRef language) {
}
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 (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;
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);
result = (CFStringRef)CFDictionaryGetValue(stringTable, key);
if (!result) {
- static int capitalize = -1;
if (!value) {
result = (CFStringRef)CFRetain(key);
} else if (CFEqual(value, CFSTR(""))) {
} else {
result = (CFStringRef)CFRetain(value);
}
- if (capitalize != 0) {
- if (capitalize != 0) {
- 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;
- }
+ __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);
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);
if (CFArrayGetCount(array) > 0) result = (CFURLRef)CFRetain(CFArrayGetValueAtIndex(array, 0));
CFRelease(array);
}
+#endif
}
if (newURL) CFRelease(newURL);
return result;
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);
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;
extern void *__CFAppleLanguages;
-#if DEPLOYMENT_TARGET_WINDOWS
-
-extern CFStringRef copyLocaleLanguageName(void);
-extern CFStringRef copyLocaleCountryName(void);
-
-static CFArrayRef copyWindowsLanguagePrefsArray() {
- CFArrayRef result;
- CFStringRef locales[4];
- CFStringRef languageName = copyLocaleLanguageName(), countryName = copyLocaleCountryName();
- if (!languageName) languageName = CFSTR("en");
- if (!countryName) countryName = CFSTR("");
- CFIndex i, localesCount = 0;
- if (CFStringGetLength(countryName) > 0) locales[localesCount++] = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@_%@"), languageName, countryName);
- if (CFStringGetLength(languageName) != 0) {
- // special-case for zh since we don't have a generic zh localization
- if (CFStringCompare(languageName, CFSTR("zh"), kCFCompareCaseInsensitive) != 0) {
- locales[localesCount++] = CFStringCreateCopy(kCFAllocatorSystemDefault, languageName);//languageName;
- } else {
- CFStringRef moreSpecificLanguageName;
-
- // See http://intrigue-build.apple.com/changeset/14948 for the details on the change. Copied below is the snippet of the code change.
- // According to http://www.microsoft.com/globaldev/reference/win2k/setup/lcid.mspx, the locales that use
- // 126 // simplified chinese are CN (PRC) and SG (Singapore). The rest use traditional chinese.
- // 127 languageName = (countryName == TEXT("CN") || countryName == TEXT("SG")) ? TEXT("zh_CN") : TEXT("zh_TW");
-
- // Compare for CN or SG
- if (CFStringCompare(countryName, CFSTR("CN"), kCFCompareCaseInsensitive) == 0 || CFStringCompare(countryName, CFSTR("SG"), kCFCompareCaseInsensitive) == 0) {
- moreSpecificLanguageName = CFSTR("zh_CN");
- } else {
- moreSpecificLanguageName = CFSTR("zh_TW");
- }
- locales[localesCount++] = CFStringCreateCopy(kCFAllocatorSystemDefault, moreSpecificLanguageName);
- }
- // Don't need this now
- if (languageName) CFRelease(languageName);
- if (countryName) CFRelease(countryName);
- }
- if (localesCount == 0) locales[localesCount++] = CFStringCreateCopy(kCFAllocatorSystemDefault, CFSTR("en"));
- result = CFArrayCreate(kCFAllocatorDefault, (const void **)locales, localesCount, &kCFTypeArrayCallBacks);
- for (i = 0; i < localesCount; i++) CFRelease(locales[i]);
- return result;
-}
-
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
-#endif
-
-static CFArrayRef _CFBundleUserLanguages = NULL;
__private_extern__ CFArrayRef _CFBundleCopyUserLanguages(Boolean useBackstops) {
- CFArrayRef result = NULL;
- static Boolean didit = false;
- CFArrayRef preferencesArray = NULL;
- // This is a temporary solution, until the argument domain is moved down into CFPreferences
- __CFSpinLock(&CFBundleResourceGlobalDataLock);
- if (!didit) {
+ static CFArrayRef _CFBundleUserLanguages = NULL;
+ static dispatch_once_t once = 0;
+ dispatch_once(&once, ^{
+ CFArrayRef preferencesArray = NULL;
if (__CFAppleLanguages) {
CFDataRef data;
CFIndex length = strlen((const char *)__CFAppleLanguages);
CFRelease(_CFBundleUserLanguages);
_CFBundleUserLanguages = NULL;
}
- didit = true;
+ if (preferencesArray) CFRelease(preferencesArray);
+ });
+
+ if (_CFBundleUserLanguages) {
+ CFRetain(_CFBundleUserLanguages);
+ return _CFBundleUserLanguages;
+ } else {
+ return NULL;
}
- __CFSpinUnlock(&CFBundleResourceGlobalDataLock);
- if (preferencesArray) CFRelease(preferencesArray);
- if (!result && _CFBundleUserLanguages) result = (CFArrayRef)CFRetain(_CFBundleUserLanguages);
- return result;
}
CF_EXPORT void _CFBundleGetLanguageAndRegionCodes(SInt32 *languageCode, SInt32 *regionCode) {
CFArrayRef predefinedLocalizations = NULL;
CFRange predefinedLocalizationsRange;
CFMutableStringRef cheapStr, tmpString;
-#if READ_DIRECTORIES
CFArrayRef contents;
CFRange contentsRange;
-#else /* READ_DIRECTORIES */
- Boolean isDir = false;
-#endif /* READ_DIRECTORIES */
// both of these used for temp string operations, for slightly
// different purposes, where each type is appropriate
_CFStrSetDesiredCapacity(cheapStr, CFMaxPathSize);
tmpString = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, NULL, 0, 0, kCFAllocatorNull);
-#if READ_DIRECTORIES
CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen);
CFStringReplaceAll(cheapStr, tmpString);
contents = _CFBundleCopySortedDirectoryContentsAtPath(cheapStr, _CFBundleAllContents);
contentsRange = CFRangeMake(0, CFArrayGetCount(contents));
-#endif /* READ_DIRECTORIES */
if (infoDict) {
predefinedLocalizations = (CFArrayRef)CFDictionaryGetValue(infoDict, kCFBundleLocalizationsKey);
CFStringGetCharacters(curLangStr, CFRangeMake(0, curLangLen), curLangUniChars);
savedPathLen = pathLen;
if (_CFAppendPathComponent(pathUniChars, &pathLen, CFMaxPathSize, curLangUniChars, curLangLen) && _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, _LprojUniChars, _LprojLen)) {
-#if READ_DIRECTORIES
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))) {
-#else /* READ_DIRECTORIES */
- CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen);
- CFStringReplaceAll(cheapStr, tmpString);
- if ((predefinedLocalizations && CFArrayContainsValue(predefinedLocalizations, predefinedLocalizationsRange, curLangStr)) || (version != 4 && _CFIsResourceAtPath(cheapStr, &isDir) && isDir)) {
-#endif /* READ_DIRECTORIES */
if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), curLangStr)) CFArrayAppendValue(lprojNames, curLangStr);
foundOne = true;
if (CFStringGetLength(curLangStr) <= 2) {
CFRelease(cheapStr);
CFRelease(tmpString);
-#if READ_DIRECTORIES
CFRelease(contents);
-#endif /* READ_DIRECTORIES */
return foundOne;
}
}
if (foundOne && altLangStr) {
CFRelease(cheapStr);
CFRelease(tmpString);
-#if READ_DIRECTORIES
CFRelease(contents);
-#endif /* READ_DIRECTORIES */
return foundOne;
}
if (altLangStr) {
CFStringGetCharacters(altLangStr, CFRangeMake(0, curLangLen), curLangUniChars);
pathLen = savedPathLen;
if (_CFAppendPathComponent(pathUniChars, &pathLen, CFMaxPathSize, curLangUniChars, curLangLen) && _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, _LprojUniChars, _LprojLen)) {
-#if READ_DIRECTORIES
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))) {
-#else /* READ_DIRECTORIES */
- CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen);
- CFStringReplaceAll(cheapStr, tmpString);
- if ((predefinedLocalizations && CFArrayContainsValue(predefinedLocalizations, predefinedLocalizationsRange, altLangStr)) || (version != 4 && _CFIsResourceAtPath(cheapStr, &isDir) && isDir)) {
-#endif /* READ_DIRECTORIES */
if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), altLangStr)) CFArrayAppendValue(lprojNames, altLangStr);
foundOne = true;
CFRelease(cheapStr);
CFRelease(tmpString);
-#if READ_DIRECTORIES
CFRelease(contents);
-#endif /* READ_DIRECTORIES */
return foundOne;
}
}
}
-#if READ_DIRECTORIES
if (!foundOne && (!predefinedLocalizations || CFArrayGetCount(predefinedLocalizations) == 0)) {
Boolean hasLocalizations = false;
CFIndex idx;
for (idx = 0; !hasLocalizations && idx < contentsRange.length; idx++) {
- CFStringRef name = CFArrayGetValueAtIndex(contents, idx);
+ CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(contents, idx);
if (CFStringHasSuffix(name, _CFBundleLprojExtensionWithDot)) hasLocalizations = true;
}
if (!hasLocalizations) {
return foundOne;
}
}
-#endif /* READ_DIRECTORIES */
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)) {
-#if READ_DIRECTORIES
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))) {
-#else /* READ_DIRECTORIES */
- CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen);
- CFStringReplaceAll(cheapStr, tmpString);
- if ((predefinedLocalizations && CFArrayContainsValue(predefinedLocalizations, predefinedLocalizationsRange, modifiedLangStr)) || (version != 4 && _CFIsResourceAtPath(cheapStr, &isDir) && isDir)) {
-#endif /* READ_DIRECTORIES */
if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), modifiedLangStr)) CFArrayAppendValue(lprojNames, modifiedLangStr);
foundOne = true;
}
CFStringGetCharacters(languageAbbreviation, CFRangeMake(0, curLangLen), curLangUniChars);
pathLen = savedPathLen;
if (_CFAppendPathComponent(pathUniChars, &pathLen, CFMaxPathSize, curLangUniChars, curLangLen) && _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, _LprojUniChars, _LprojLen)) {
-#if READ_DIRECTORIES
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))) {
-#else /* READ_DIRECTORIES */
- CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen);
- CFStringReplaceAll(cheapStr, tmpString);
- if ((predefinedLocalizations && CFArrayContainsValue(predefinedLocalizations, predefinedLocalizationsRange, languageAbbreviation)) || (version != 4 && _CFIsResourceAtPath(cheapStr, &isDir) && isDir)) {
-#endif /* READ_DIRECTORIES */
if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageAbbreviation)) CFArrayAppendValue(lprojNames, languageAbbreviation);
foundOne = true;
}
CFStringGetCharacters(languageName, CFRangeMake(0, curLangLen), curLangUniChars);
pathLen = savedPathLen;
if (_CFAppendPathComponent(pathUniChars, &pathLen, CFMaxPathSize, curLangUniChars, curLangLen) && _CFAppendPathExtension(pathUniChars, &pathLen, CFMaxPathSize, _LprojUniChars, _LprojLen)) {
-#if READ_DIRECTORIES
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))) {
-#else /* READ_DIRECTORIES */
- CFStringSetExternalCharactersNoCopy(tmpString, pathUniChars, pathLen, pathLen);
- CFStringReplaceAll(cheapStr, tmpString);
- if ((predefinedLocalizations && CFArrayContainsValue(predefinedLocalizations, predefinedLocalizationsRange, languageName)) || (version != 4 && _CFIsResourceAtPath(cheapStr, &isDir) && isDir)) {
-#endif /* READ_DIRECTORIES */
if (!CFArrayContainsValue(lprojNames, CFRangeMake(0, CFArrayGetCount(lprojNames)), languageName)) CFArrayAppendValue(lprojNames, languageName);
foundOne = true;
}
if (canonicalLanguageAbbreviation) CFRelease(canonicalLanguageAbbreviation);
CFRelease(cheapStr);
CFRelease(tmpString);
-#if READ_DIRECTORIES
CFRelease(contents);
-#endif /* READ_DIRECTORIES */
return foundOne;
}
static Boolean CFBundleAllowMixedLocalizations(void) {
- static Boolean allowMixed = false, examinedMain = false;
- if (!examinedMain) {
+ 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;
SInt32 val = 0;
if (CFNumberGetValue((CFNumberRef)allowMixedValue, kCFNumberSInt32Type, &val)) allowMixed = (val != 0);
}
- }
- examinedMain = true;
- }
+ }
+ });
return allowMixed;
}
// version 3: none of the above (see below)
// version 4: not a bundle (for main bundle only)
uint8_t localVersion = 3;
-#if READ_DIRECTORIES
CFURLRef absoluteURL = CFURLCopyAbsoluteURL(url);
CFStringRef directoryPath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
CFArrayRef contents = _CFBundleCopySortedDirectoryContentsAtPath(directoryPath, _CFBundleAllContents);
- if (CFStringHasSuffix(CFURLGetString(url), CFSTR(".framework/"))) {
+ Boolean hasFrameworkSuffix = CFStringHasSuffix(CFURLGetString(url), CFSTR(".framework/"));
+#if DEPLOYMENT_TARGET_WINDOWS
+ hasFrameworkSuffix = hasFrameworkSuffix || CFStringHasSuffix(CFURLGetString(url), CFSTR(".framework\\"));
+#endif
+
+ if (hasFrameworkSuffix) {
if (_CFBundleSortedArrayContains(contents, _CFBundleResourcesDirectoryName)) localVersion = 0;
else if (_CFBundleSortedArrayContains(contents, _CFBundleSupportFilesDirectoryName2)) localVersion = 2;
else if (_CFBundleSortedArrayContains(contents, _CFBundleSupportFilesDirectoryName1)) localVersion = 1;
CFRelease(contents);
CFRelease(directoryPath);
CFRelease(absoluteURL);
-#endif /* READ_DIRECTORIES */
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_WINDOWS
if (localVersion == 3) {
-#if DEPLOYMENT_TARGET_EMBEDDED
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_WINDOWS
-#if DEPLOYMENT_TARGET_WINDOWS
- if (CFStringHasSuffix(CFURLGetString(url), CFSTR(".framework/")) || CFStringHasSuffix(CFURLGetString(url), CFSTR(".framework\\"))) {
-#else
- if (CFStringHasSuffix(CFURLGetString(url), CFSTR(".framework/"))) {
-#endif
+ if (hasFrameworkSuffix) {
if (_CFBundleURLHasSubDir(url, _CFBundleResourcesURLFromBase0)) localVersion = 0;
else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase2)) localVersion = 2;
else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase1)) localVersion = 1;
else if (_CFBundleURLHasSubDir(url, _CFBundleResourcesURLFromBase0)) localVersion = 0;
else if (_CFBundleURLHasSubDir(url, _CFBundleSupportFilesURLFromBase1)) localVersion = 1;
}
-#endif
}
+#endif
if (version) *version = localVersion;
return (localVersion != 3);
}
}
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;
}
CFMutableStringRef cheapStr;
CFStringRef infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension0, infoURLFromBase = _CFBundleInfoURLFromBase0;
Boolean tryPlatformSpecific = true, tryGlobal = true;
-#if READ_DIRECTORIES
CFURLRef directoryURL = NULL, absoluteURL;
CFStringRef directoryPath;
CFArrayRef contents = NULL;
CFRange contentsRange = CFRangeMake(0, 0);
-#endif /* READ_DIRECTORIES */
_CFEnsureStaticBuffersInited();
if (0 == version) {
-#if READ_DIRECTORIES
directoryURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleResourcesURLFromBase0, url);
-#endif /* READ_DIRECTORIES */
infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension0;
infoURLFromBase = _CFBundleInfoURLFromBase0;
} else if (1 == version) {
-#if READ_DIRECTORIES
directoryURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleSupportFilesURLFromBase1, url);
-#endif /* READ_DIRECTORIES */
infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension1;
infoURLFromBase = _CFBundleInfoURLFromBase1;
} else if (2 == version) {
-#if READ_DIRECTORIES
directoryURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleSupportFilesURLFromBase2, url);
-#endif /* READ_DIRECTORIES */
infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension2;
infoURLFromBase = _CFBundleInfoURLFromBase2;
} else if (3 == version) {
// 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))) {
-#if READ_DIRECTORIES
- directoryURL = CFRetain(url);
-#endif /* READ_DIRECTORIES */
+ directoryURL = (CFURLRef)CFRetain(url);
infoURLFromBaseNoExtension = _CFBundleInfoURLFromBaseNoExtension3;
infoURLFromBase = _CFBundleInfoURLFromBase3;
}
CFRelease(path);
}
}
-#if READ_DIRECTORIES
if (directoryURL) {
absoluteURL = CFURLCopyAbsoluteURL(directoryURL);
directoryPath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
CFRelease(absoluteURL);
CFRelease(directoryURL);
}
-#endif /* READ_DIRECTORIES */
len = CFStringGetLength(infoURLFromBaseNoExtension);
CFStringGetCharacters(infoURLFromBaseNoExtension, CFRangeMake(0, len), buff);
cheapStr = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
CFStringAppendCharacters(cheapStr, buff, len);
infoURL = CFURLCreateWithString(kCFAllocatorSystemDefault, cheapStr, url);
-#if READ_DIRECTORIES
if (contents) {
CFIndex resourcesLen, idx;
- for (resourcesLen = len; resourcesLen > 0; resourcesLen--) if (buff[resourcesLen - 1] == '/') break;
+ 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, CFArrayGetValueAtIndex(contents, idx), kCFCompareCaseInsensitive)) tryPlatformSpecific = true;
+ if (kCFCompareEqualTo == CFStringCompare(cheapStr, (CFStringRef)CFArrayGetValueAtIndex(contents, idx), kCFCompareCaseInsensitive)) tryPlatformSpecific = true;
}
}
-#endif /* READ_DIRECTORIES */
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);
// Check for global Info.plist
CFRelease(infoURL);
infoURL = CFURLCreateWithString(kCFAllocatorSystemDefault, infoURLFromBase, url);
-#if READ_DIRECTORIES
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, CFArrayGetValueAtIndex(contents, idx), kCFCompareCaseInsensitive)) tryGlobal = true;
+ if (kCFCompareEqualTo == CFStringCompare(_CFBundleInfoFileName, (CFStringRef)CFArrayGetValueAtIndex(contents, idx), kCFCompareCaseInsensitive)) tryGlobal = true;
}
}
-#endif /* READ_DIRECTORIES */
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"));
}
}
CFRelease(infoURL);
-#if READ_DIRECTORIES
if (contents) CFRelease(contents);
-#endif /* READ_DIRECTORIES */
}
_processInfoDictionary((CFMutableDictionaryRef)result, _CFGetPlatformName(), _CFGetProductName());
return result;
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)'/')) {
+ 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)'/')) {
+ } 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)'/')) {
+ } 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)'/')) {
+ } 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)'/')) {
+ } 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 {
CF_EXPORT CFStringRef _CFBundleGetCurrentPlatform(void) {
#if DEPLOYMENT_TARGET_MACOSX
return CFSTR("MacOS");
-#elif DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
return CFSTR("iPhoneOS");
#elif DEPLOYMENT_TARGET_WINDOWS
return CFSTR("Windows");
}
__private_extern__ CFStringRef _CFBundleGetPlatformExecutablesSubdirectoryName(void) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
return CFSTR("MacOS");
#elif DEPLOYMENT_TARGET_WINDOWS
return CFSTR("Windows");
}
__private_extern__ CFStringRef _CFBundleGetAlternatePlatformExecutablesSubdirectoryName(void) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
return CFSTR("Mac OS X");
#elif DEPLOYMENT_TARGET_WINDOWS
return CFSTR("WinNT");
}
__private_extern__ CFStringRef _CFBundleGetOtherPlatformExecutablesSubdirectoryName(void) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
return CFSTR("MacOSClassic");
#elif DEPLOYMENT_TARGET_WINDOWS
return CFSTR("Other");
}
__private_extern__ CFStringRef _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName(void) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
return CFSTR("Mac OS 8");
#elif DEPLOYMENT_TARGET_WINDOWS
return CFSTR("Other");
CF_EXPORT CFArrayRef CFBundleCopyBundleLocalizations(CFBundleRef bundle) {
CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
-#if READ_DIRECTORIES
CFURLRef absoluteURL;
CFStringRef directoryPath;
CFArrayRef contents;
CFRange contentsRange;
CFIndex idx;
-#else /* READ_DIRECTORIES */
- CFArrayRef urls = ((_CFBundleLayoutVersion(bundle) != 4) ? _CFContentsOfDirectory(CFGetAllocator(bundle), NULL, NULL, resourcesURL, _CFBundleLprojExtension) : NULL);
-#endif /* READ_DIRECTORIES */
CFArrayRef predefinedLocalizations = NULL;
CFMutableArrayRef result = NULL;
}
}
-#if READ_DIRECTORIES
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 = CFArrayGetValueAtIndex(contents, 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);
CFRelease(directoryPath);
CFRelease(absoluteURL);
}
-#else /* READ_DIRECTORIES */
- if (urls) {
- CFIndex i, c = CFArrayGetCount(urls);
- CFURLRef curURL, curAbsoluteURL;
- CFStringRef curStr, regionStr;
- UniChar buff[CFMaxPathSize];
- CFIndex strLen, startOfLastPathComponent, regionLen;
-
- if (c > 0 && !result) result = CFArrayCreateMutable(CFGetAllocator(bundle), 0, &kCFTypeArrayCallBacks);
- for (i = 0; i < c; i++) {
- curURL = (CFURLRef)CFArrayGetValueAtIndex(urls, i);
- curAbsoluteURL = CFURLCopyAbsoluteURL(curURL);
- curStr = CFURLCopyFileSystemPath(curAbsoluteURL, PLATFORM_PATH_STYLE);
- CFRelease(curAbsoluteURL);
- strLen = CFStringGetLength(curStr);
- if (strLen > CFMaxPathSize) strLen = CFMaxPathSize;
- CFStringGetCharacters(curStr, CFRangeMake(0, strLen), buff);
-
- startOfLastPathComponent = _CFStartOfLastPathComponent(buff, strLen);
- regionLen = _CFLengthAfterDeletingPathExtension(&(buff[startOfLastPathComponent]), strLen - startOfLastPathComponent);
- regionStr = CFStringCreateWithCharacters(CFGetAllocator(bundle), &(buff[startOfLastPathComponent]), regionLen);
- CFArrayAppendValue(result, regionStr);
- CFRelease(regionStr);
- CFRelease(curStr);
- }
- CFRelease(urls);
- }
-#endif /* READ_DIRECTORIES */
if (!result) {
CFStringRef developmentLocalization = CFBundleGetDevelopmentRegion(bundle);
}
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;
+ if (backward) {
+ for (CFIndex i = start; i > start-length; i--) {
+ if (c == str[i]) {
+ result->location = i;
+ found = true;
+ break;
+ }
+ }
+ } else {
+ for (CFIndex i = start; i < start+length; i++) {
+ if (c == str[i]) {
+ result->location = i;
+ found = true;
+ break;
+ }
+ }
+ }
+ return found;
+}
+
+
+typedef enum {
+ _CFBundleFileVersionNoProductNoPlatform = 1,
+ _CFBundleFileVersionWithProductNoPlatform,
+ _CFBundleFileVersionNoProductWithPlatform,
+ _CFBundleFileVersionWithProductWithPlatform,
+ _CFBundleFileVersionUnmatched
+} _CFBundleFileVersion;
+
+static _CFBundleFileVersion _CFBundleCheckFileProductAndPlatform(CFStringRef file, UniChar *fileBuffer1, CFIndex fileLen, CFRange searchRange, CFStringRef product, CFStringRef platform, CFRange* prodp, CFRange* platp, CFIndex prodLen)
+{
+ _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)) {
+ foundprod = YES;
+ }
+ }
+ if (!foundprod) {
+ for (CFIndex i = 0; i < _CFBundleNumberOfProducts; i++) {
+ if (CFStringFindWithOptions(file, _CFBundleSupportedProducts[i], searchRange, kCFCompareEqualTo, &found)) {
+ wrong = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!wrong && _CFBundleFindCharacterInStr(fileBuffer, '-', NO, searchRange.location, searchRange.length, &found)) {
+ if (CFStringFindWithOptions(file, platform, searchRange, kCFCompareEqualTo, platp)) {
+ foundplat = YES;
+ }
+ if (!foundplat) {
+ for (CFIndex i = 0; i < _CFBundleNumberOfPlatforms; i++) {
+ if (CFStringFindWithOptions(file, _CFBundleSupportedPlatforms[i], searchRange, kCFCompareEqualTo, &found)) {
+ wrong = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (wrong) {
+ version = _CFBundleFileVersionUnmatched;
+ } else if (foundplat && foundprod) {
+ version = _CFBundleFileVersionWithProductWithPlatform;
+ } else if (foundplat) {
+ version = _CFBundleFileVersionNoProductWithPlatform;
+ } else if (foundprod) {
+ version = _CFBundleFileVersionWithProductNoPlatform;
+ } else {
+ version = _CFBundleFileVersionNoProductNoPlatform;
+ }
+ return version;
+}
+
+
+// ZFH
+
+
+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);
+ }
+}
+
+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);
+
+ 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);
+ }
+
+ if (subDirLen) {
+ memmove(valueBuff+pathOfDirWithSlashLen, subDir, subDirLen*sizeof(UniChar));
+ pathOfDirWithSlashLen += subDirLen;
+ if (subDir[subDirLen-1] != _CFGetSlash()) {
+ _CFAppendTrailingPathSlash(valueBuff, &pathOfDirWithSlashLen, valueBufferLen);
+ }
+ }
+
+ 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
+
+#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;
+
+ if (pathInUTF8Len + 2 >= CFMaxPathLength) {
+ result = false;
+ }
+
+ 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;
+ }
+
+ do {
+ CFIndex nameLen = wcslen(filePt.cFileName);
+ if (filePt.cFileName[0] == '.' && (nameLen == 1 || (nameLen == 2 && filePt.cFileName[1] == '.'))) {
+ continue;
+ }
+ 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);
+ }
+ } 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) {
+ case _CFBundleFileVersionWithProductNoPlatform:
+ platformRange = productRange;
+ searchOffset = productLen;
+ 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);
+ }
+ 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;
+ }
+
+ free(cPathBuff);
+ CFAllocatorDeallocate(kCFAllocatorSystemDefault, valueBuff);
+ CFRelease(valueStr);
+ return result;
+}
+
+__private_extern__ CFDictionaryRef _CFBundleCreateQueryTableAtPath(CFBundleRef bundle, CFURLRef bundleURL, CFArrayRef languages, UniChar *resDir, CFIndex resDirLen, UniChar *subDir, CFIndex subDirLen)
+{
+ 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);
+ CFMutableDictionaryRef typeDir = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFMutableStringRef type = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, NULL, 0, 0, kCFAllocatorNull);
+
+ CFStringRef productName = _CFGetProductName();//CFSTR("iphone");
+ CFStringRef platformName = _CFGetPlatformName();//CFSTR("iphoneos");
+ if (CFEqual(productName, CFSTR("ipod"))) {
+ productName = CFSTR("iphone");
+ }
+ CFStringRef product = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("~%@"), productName);
+ CFStringRef platform = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("-%@"), platformName);
+
+ CFStringRef bundlePath = NULL;
+ if (bundle) {
+ bundlePath = _CFBundleGetBundlePath(bundle);
+ CFRetain(bundlePath);
+ } else {
+ CFURLRef url = CFURLCopyAbsoluteURL(bundleURL);
+ bundlePath = CFURLCopyFileSystemPath(url, PLATFORM_PATH_STYLE);
+ CFRelease(url);
+ }
+ // 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);
+ }
+
+ CFStringRef basePath = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, pathBuffer, pathLen);
+
+ if (subDirLen > 0) { // should not fail, buffer has enought space
+ appendSucc = _CFAppendPathComponent(pathBuffer, &pathLen, pathBufferSize, subDir, subDirLen);
+ }
+
+ 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);
+
+ CFIndex numOfAllFiles = CFArrayGetCount(allFiles);
+
+ if (bundle && !languages) {
+ languages = _CFBundleGetLanguageSearchList(bundle);
+ }
+ 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);
+
+ if (!hasFileAdded && numOfAllFiles < CFArrayGetCount(allFiles)) {
+ hasFileAdded = true;
+ }
+ firstLproj = false;
+ }
+
+ // 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);
+ }
+ 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);
+
+ 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);
+ }
+ 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);
+
+ if (!hasFileAdded && numOfAllFiles < CFArrayGetCount(allFiles)) {
+ hasFileAdded = true;
+ }
+ }
+ }
+
+ CFRelease(addedTypes);
+
+ // put the array of all files in sub dir to the query table
+ if (CFArrayGetCount(allFiles) > 0) {
+ CFDictionarySetValue(queryTable, _CFBundleAllFiles, allFiles);
+ }
+
+ CFRelease(platform);
+ CFRelease(product);
+ 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)
+{
+ 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);
+ } else {
+ url = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, urlStr, PLATFORM_PATH_STYLE, NO);
+ }
+
+ return url;
+}
+
+static CFURLRef _CFBundleCreateRelativeURLFromBaseAndPath(CFStringRef path, CFURLRef base, UniChar slash, CFStringRef slashStr)
+{
+ CFURLRef url = NULL;
+ CFRange resultRange;
+ Boolean needToRelease = false;
+ if (CFStringFindWithOptions(path, slashStr, CFRangeMake(0, CFStringGetLength(path)-1), kCFCompareBackwards, &resultRange)) {
+ CFStringRef subPathCom = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, path, CFRangeMake(0, resultRange.location));
+ base = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, base, subPathCom, YES);
+ path = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, path, CFRangeMake(resultRange.location+1, CFStringGetLength(path)-resultRange.location-1));
+ CFRelease(subPathCom);
+ needToRelease = true;
+ }
+ if (CFStringGetCharacterAtIndex(path, CFStringGetLength(path)-1) == slash) {
+ url = (CFURLRef)CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, path, PLATFORM_PATH_STYLE, YES, base);
+ } else {
+ url = (CFURLRef)CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, path, PLATFORM_PATH_STYLE, NO, base);
+ }
+ if (needToRelease) {
+ CFRelease(base);
+ CFRelease(path);
+ }
+ return url;
+}
+
+static void _CFBundleFindResourcesWithPredicate(CFMutableArrayRef interResult, CFDictionaryRef queryTable, Boolean (^predicate)(CFStringRef filename, Boolean *stop), Boolean *stop)
+{
+ CFIndex dictSize = CFDictionaryGetCount(queryTable);
+ if (dictSize == 0) {
+ return;
+ }
+ STACK_BUFFER_DECL(CFTypeRef, keys, dictSize);
+ STACK_BUFFER_DECL(CFTypeRef, values, dictSize);
+ CFDictionaryGetKeysAndValues(queryTable, keys, values);
+ for (CFIndex i = 0; i < dictSize; i++) {
+ if (predicate((CFStringRef)keys[i], stop)) {
+ if (CFGetTypeID(values[i]) == CFStringGetTypeID()) {
+ CFArrayAppendValue(interResult, values[i]);
+ } else {
+ CFArrayAppendArray(interResult, (CFArrayRef)values[i], CFRangeMake(0, CFArrayGetCount((CFArrayRef)values[i])));
+ }
+ }
+
+ 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))
+{
+ CFTypeRef value = NULL;
+ Boolean stop = false; // for predicate
+ CFMutableArrayRef interResult = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
+ CFDictionaryRef subTable = NULL;
+
+ if (1 == bundleVersion) {
+ CFIndex savedResDirLen = resDirLen;
+ // 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);
+ }
+ }
+ resDirLen = savedResDirLen;
+ }
+
+ if (!value && !stop) {
+ if (subTable) CFRelease(subTable);
+ subTable = _CFBundleCopyQueryTable(bundle, bundleURL, languages, resDir, resDirLen, subDirBuffer, subDirLen);
+ if (predicate) {
+ _CFBundleFindResourcesWithPredicate(interResult, subTable, predicate, &stop);
+ } else {
+ // get the path or paths for the given key
+ value = CFDictionaryGetValue(subTable, key);
+ }
+ }
+
+ // if localization is needed, we filter out the paths for the localization and put the valid ones in the interResult
+ Boolean checkLP = true;
+ CFIndex lpLen = lproj ? CFStringGetLength(lproj) : 0;
+ if (localized && value) {
+
+ if (CFGetTypeID(value) == CFStringGetTypeID()){
+ // We had one result, but since we are going to do a search in a different localization, we will convert the one result into an array of results.
+ value = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)&value, 1, &kCFTypeArrayCallBacks);
+ } else {
+ CFRetain(value);
+ }
+
+ CFRange resultRange, searchRange;
+ CFIndex pathValueLen;
+ CFIndex limit = returnArray ? CFArrayGetCount((CFArrayRef)value) : 1;
+ searchRange.location = 0;
+ for (CFIndex i = 0; i < limit; i++) {
+ CFStringRef pathValue = (CFStringRef) CFArrayGetValueAtIndex((CFArrayRef)value, i);
+ pathValueLen = CFStringGetLength(pathValue);
+ searchRange.length = pathValueLen;
+
+ // 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 (CFStringFindWithOptions(pathValue, subDir, searchRange, kCFCompareEqualTo, &resultRange) && resultRange.location != searchRange.location) {
+ searchForLocalization = true;
+ }
+ } else if (!subDirLen && searchRange.length != 0) {
+ if (CFStringFindWithOptions(pathValue, _CFBundleLprojExtensionWithDot, searchRange, kCFCompareEqualTo, &resultRange) && resultRange.location + 7 < pathValueLen) {
+ searchForLocalization = true;
+ }
+ }
+
+ if (searchForLocalization) {
+ if (!lpLen || !(CFStringFindWithOptions(pathValue, lproj, searchRange, kCFCompareEqualTo | kCFCompareAnchored, &resultRange) && CFStringFindWithOptions(pathValue, CFSTR("."), CFRangeMake(resultRange.location + resultRange.length, 1), kCFCompareEqualTo, &resultRange))) {
+ break;
+ }
+ checkLP = false;
+ }
+
+ CFArrayAppendValue(interResult, pathValue);
+ }
+
+ CFRelease(value);
+
+ if (!returnArray && CFArrayGetCount(interResult) != 0) {
+ checkLP = false;
+ }
+ } else if (value) {
+ if (CFGetTypeID(value) == CFArrayGetTypeID()) {
+ CFArrayAppendArray(interResult, (CFArrayRef)value, CFRangeMake(0, CFArrayGetCount((CFArrayRef)value)));
+ } else {
+ CFArrayAppendValue(interResult, value);
+ }
+ }
+
+ value = NULL;
+ CFRelease(subTable);
+
+ // 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);
+ }
+ subTable = _CFBundleCopyQueryTable(bundle, bundleURL, languages, resDir, resDirLen, lprojBuff, subDirLen+lprojBuffLen);
+
+ value = CFDictionaryGetValue(subTable, key);
+
+ if (value) {
+ if (CFGetTypeID(value) == CFStringGetTypeID()) {
+ CFArrayAppendValue(interResult, value);
+ } else {
+ CFArrayAppendArray(interResult, (CFArrayRef)value, CFRangeMake(0, CFArrayGetCount((CFArrayRef)value)));
+ }
+ }
+
+ CFRelease(subTable);
+ }
+
+ // after getting paths, we create urls from the paths
+ 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;
+ if (bundle) {
+ bundlePath = _CFBundleGetBundlePath(bundle);
+ CFRetain(bundlePath);
+ } else {
+ CFURLRef url = CFURLCopyAbsoluteURL(bundleURL);
+ bundlePath = CFURLCopyFileSystemPath(url, PLATFORM_PATH_STYLE);
+ CFRelease(url);
+ }
+ CFIndex urlBufferLen = CFStringGetLength(bundlePath);
+ CFStringGetCharacters(bundlePath, CFRangeMake(0, urlBufferLen), urlBuffer);
+ CFRelease(bundlePath);
+
+ if (resDirLen) {
+ _CFAppendPathComponent(urlBuffer, &urlBufferLen, CFMaxPathSize, resDir, resDirLen);
+ }
+ _CFAppendTrailingPathSlash(urlBuffer, &urlBufferLen, CFMaxPathSize);
+
+ if (!returnArray) {
+ Boolean isOnlyTypeOrAllFiles = CFStringHasPrefix(key, _CFBundleTypeIndicator);
+ isOnlyTypeOrAllFiles |= CFStringHasPrefix(key, _CFBundleAllFiles);
+
+ 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);
+ 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);
+ 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);
+ CFArrayAppendValue(urls, url);
+ CFRelease(url);
+ }
+ result = urls;
+ CFRelease(base);
+ }
+ CFRelease(urlStr);
+ CFAllocatorDeallocate(kCFAllocatorSystemDefault, urlBuffer);
+ } else if (returnArray) {
+ result = CFRetain(interResult);
+ }
+
+ 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))
+{
+ CFIndex rnameLen = 0;
+ CFIndex typeLen = resourceType ? CFStringGetLength(resourceType) : 0;
+ CFIndex lprojLen = lproj ? CFStringGetLength(lproj) + 7 : 0; // 7 is the length of ".lproj/"
+ 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);
+ }
+
+ 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);
+ } else {
+ key = (CFStringRef)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);
+ }
+ }
+
+ // Init the one-time-only unichar buffers.
+ _CFEnsureStaticBuffersInited();
+
+ 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);
+
+ if ((!returnValue || (CFGetTypeID(returnValue) == CFArrayGetTypeID() && CFArrayGetCount((CFArrayRef)returnValue) == 0)) && (0 == bundleVersion || 2 == bundleVersion)) {
+ CFStringRef bundlePath = NULL;
+ if (bundle) {
+ bundlePath = _CFBundleGetBundlePath(bundle);
+ CFRetain(bundlePath);
+ } else {
+ CFURLRef absoluteURL = CFURLCopyAbsoluteURL(bundleURL);
+ bundlePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
+ CFRelease(absoluteURL);
+ }
+ if ((0 == bundleVersion) || CFEqual(CFSTR("/Library/Spotlight"), bundlePath)){
+ 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;
+ } else {
+ resDirLen = 0;
+ }
+ 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);
+ }
+ CFRelease(bundlePath);
+ }
+
+ if (resourceName) CFRelease(resourceName);
+ if (subPath) CFRelease(subPath);
+ 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);
+}
--- /dev/null
+/*
+ * Copyright (c) 2012 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@
+ */
+
+/* CFBurstTrie.c
+ Copyright (c) 2008-2012, Apple Inc. All rights reserved.
+ Responsibility: Jennifer Moore
+*/
+
+#include "CFInternal.h"
+#include "CFBurstTrie.h"
+#include "CFByteOrder.h"
+#include "CFNumber.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <limits.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/mman.h>
+#endif
+
+#include <errno.h>
+#include <assert.h>
+
+#if DEPLOYMENT_TARGET_WINDOWS
+#define open _NS_open
+#define statinfo _stat
+#define stat(x,y) _NS_stat(x,y)
+#define __builtin_memcmp(x, y, z) memcmp(x, y, z)
+#define __builtin_popcountll(x) popcountll(x)
+#define bzero(dst, size) ZeroMemory(dst, size)
+#define S_IWUSR 0
+#define S_IRUSR 0
+
+static int pwrite(int fd, const void *buf, size_t nbyte, off_t offset) {
+ // Get where we are
+ long pos = _tell(fd);
+
+ // Move to new offset
+ _lseek(fd, offset, SEEK_SET);
+
+ // Write data
+ int res = _write(fd, buf, nbyte);
+
+ // Return to previous offset
+ _lseek(fd, pos, SEEK_SET);
+
+ return res;
+}
+
+#else
+#define statinfo stat
+#endif
+
+#if 0
+#pragma mark Types and Utilities
+#endif
+
+#define MAX_STRING_ALLOCATION_SIZE 342
+#define MAX_STRING_SIZE 1024
+#define MAX_KEY_LENGTH MAX_STRING_SIZE * 4
+#define CHARACTER_SET_SIZE 256
+#define MAX_LIST_SIZE 256 // 64
+#define MAX_BITMAP_SIZE 200
+#define MAX_BUFFER_SIZE (4096<<2)
+
+#define NextTrie_GetPtr(p) (p & ((~(uintptr_t)0)-3))
+#define NextTrie_GetKind(p) (p & 3)
+#define NextTrie_SetKind(p, kind) (p |= (3&kind))
+
+#define DiskNextTrie_GetPtr(map,offset) (((uintptr_t)map) + (uintptr_t)(offset & ((~(uintptr_t)0)-3)))
+#define DiskNextTrie_GetKind(p) (p & 3)
+#define DiskNextTrie_SetKind(p, kind) (p |= (3&kind))
+
+// Use this macro to avoid forgetting to check the pointer before assigning value to it.
+#define SetPayload(pointer, value) do { if (pointer) *pointer = value; } while (0)
+
+enum { Nothing = 0, TrieKind = 1, ListKind = 2, CompactTrieKind = 3 };
+typedef enum { FailedInsert = 0, NewTerm = 1, ExistingTerm = 2 } CFBTInsertCode;
+
+#pragma pack (1)
+typedef uintptr_t NextTrie;
+
+typedef struct _TrieLevel {
+ NextTrie slots[CHARACTER_SET_SIZE];
+ uint32_t weight;
+ uint32_t payload;
+} TrieLevel;
+typedef TrieLevel *TrieLevelRef;
+
+typedef struct _MapTrieLevel {
+ uint32_t slots[CHARACTER_SET_SIZE];
+ uint32_t payload;
+} MapTrieLevel;
+typedef MapTrieLevel *MapTrieLevelRef;
+
+typedef struct _CompactMapTrieLevel {
+ uint64_t bitmap[CHARACTER_SET_SIZE / 64];
+ uint32_t payload;
+ uint32_t slots[];
+} CompactMapTrieLevel;
+typedef CompactMapTrieLevel *CompactMapTrieLevelRef;
+
+typedef struct _ListNode {
+ struct _ListNode *next;
+ uint32_t weight;
+ uint32_t payload;
+ uint16_t length;
+ UInt8 string[];
+}* ListNodeRef;
+
+typedef struct _Page {
+ uint32_t length;
+ char data[];
+} Page;
+
+typedef struct _PageEntryPacked {
+ uint8_t pfxLen;
+ uint16_t strlen;
+ uint32_t payload;
+ UInt8 string[];
+} PageEntryPacked;
+
+typedef struct _PageEntry {
+ uint16_t strlen;
+ uint32_t payload;
+ UInt8 string[];
+} PageEntry;
+
+typedef struct _TrieHeader {
+ uint32_t signature;
+ uint32_t rootOffset;
+ uint32_t count;
+ uint32_t size;
+ uint32_t flags;
+ uint64_t reserved[16];
+} TrieHeader;
+
+typedef struct _TrieCursor {
+ uint64_t signature;
+ uint64_t counter;
+ NextTrie next;
+ uint32_t keylen;
+ uint32_t prefixlen;
+ const uint8_t *prefix;
+ uint8_t key[MAX_KEY_LENGTH];
+} TrieCursor;
+
+typedef struct _MapCursor {
+ uint64_t signature;
+ TrieHeader *header;
+ uint32_t next;
+ uint32_t prefixlen;
+ uint32_t keylen;
+ const uint8_t *prefix;
+ uint8_t key[MAX_STRING_SIZE*4];
+} MapCursor;
+
+typedef struct _CompactMapCursor {
+ uint32_t next;
+ uint32_t entryOffsetInPage;
+ uint32_t offsetInEntry;
+ uint32_t payload;
+ // On a page, the first entry could has 0 strlen. So we need this variable to tell us whether
+ // the cursor is merely pointing at the beginning of the page, or the first entry.
+ // For example, if the trie contains "ab" and "abc", where "a" is stored on an array level,
+ // while "b" and "bc" are stored on a page level. If we creat a cursor for string "a", this cursor
+ // will point at the beginning of the page, but not at any particular key. The both entryOffsetInPage and
+ // offsetInEntry fields of the cursor are set to 0 in this case. Now if we add "a" to the
+ // trie. the page level will actually contains three entries. The first entry corresponds to string "a".
+ // That entry has 0 strlen value. If we creat a cursor for string "a" again, this cursor will
+ // point at the first entry on the page. But the entryOffsetInPage and offsetInEntry fields are still
+ // set to 0s. So we need an additional variable to make distinction between these two situations.
+ BOOL isOnPage;
+} CompactMapCursor;
+typedef struct _CompactMapCursor *MapCursorRef;
+
+enum {
+ _kCFBurstTrieCursorTrieType = 0,
+ _kCFBurstTrieCursorMapType
+};
+
+typedef struct _CFBurstTrieCursor {
+ CompactMapCursor mapCursor;
+ CFIndex cursorType;
+ CFBurstTrieRef trie;
+} _CFBurstTrieCursor;
+
+// ** Legacy
+typedef struct _DiskTrieLevel {
+ uint32_t slots[CHARACTER_SET_SIZE];
+ uint32_t weight;
+ uint32_t payload;
+} DiskTrieLevel;
+typedef DiskTrieLevel *DiskTrieLevelRef;
+
+typedef struct _CompactDiskTrieLevel {
+ uint64_t bitmap[CHARACTER_SET_SIZE / 64]; // CHARACTER_SET_SIZE / 64bits per word
+ uint32_t weight;
+ uint32_t payload;
+ uint32_t slots[];
+} CompactDiskTrieLevel;
+typedef CompactDiskTrieLevel *CompactDiskTrieLevelRef;
+
+typedef struct _StringPage {
+ uint32_t length;
+ char data[];
+} StringPage;
+
+typedef struct _StringPageEntryPacked {
+ uint8_t pfxLen;
+ uint16_t strlen; // make uint8_t if possible
+ uint32_t payload;
+ char string[];
+} StringPageEntryPacked;
+
+typedef struct _StringPageEntry {
+ uint16_t strlen; // make uint8_t if possible
+ uint32_t payload;
+ char string[];
+} StringPageEntry;
+
+typedef struct _fileHeader {
+ uint32_t signature;
+ uint32_t rootOffset;
+ uint32_t count;
+ uint32_t size;
+ uint32_t flags;
+} fileHeader;
+// **
+#pragma pack()
+
+struct _CFBurstTrie {
+ union {
+ TrieLevel root;
+ DiskTrieLevel diskRoot;
+ MapTrieLevel maproot;
+ };
+ char *mapBase;
+ uint32_t mapSize;
+ uint32_t mapOffset;
+ uint32_t cflags;
+ uint32_t count;
+ uint32_t containerSize;
+ int retain;
+#if DEPLOYMENT_TARGET_WINDOWS
+ HANDLE mapHandle;
+ HANDLE mappedFileHandle;
+#endif
+};
+
+#if 0
+#pragma mark -
+#pragma mark Forward declarations
+#endif
+
+typedef struct _TraverseContext {
+ void *context;
+ void (*callback)(void*, const UInt8*, uint32_t, uint32_t);
+} TraverseContext;
+
+bool foundKey(void *context, const uint8_t *key, uint32_t payload, bool exact)
+{
+ if (context != NULL) {
+ TraverseContext *ctx = (TraverseContext *)context;
+ if (ctx->context && ctx->callback) {
+ ctx->callback(ctx->context, key, 1, payload);
+ }
+ }
+ return false;
+}
+
+void CFBurstTrieTraverseWithCursor(CFBurstTrieRef trie, const uint8_t *prefix, uint32_t prefixLen, void **cursor, void *ctx, bool (*callback)(void *, const uint8_t *, uint32_t, bool));
+
+static CFBTInsertCode addCFBurstTrieLevel(CFBurstTrieRef trie, TrieLevelRef root, const uint8_t *key, uint32_t keylen, uint32_t weight, uint32_t payload);
+
+static void findCFBurstTrieLevel(CFBurstTrieRef trie, TrieCursor *cursor, bool exactmatch, void *ctx, bool (*callback)(void*, const uint8_t*, uint32_t, bool));
+static void findCFBurstTrieMappedLevel(CFBurstTrieRef trie, MapCursor *cursor, bool exactmatch, void *ctx, bool (*callback)(void*, const uint8_t*, uint32_t, bool));
+static void traverseCFBurstTrieLevel(CFBurstTrieRef trie, TrieLevelRef root, TrieCursor *cursor, bool exactmatch, void *ctx, bool (*callback)(void *, const uint8_t *, uint32_t, bool));
+static void traverseCFBurstTrieMappedLevel(CFBurstTrieRef trie, MapTrieLevelRef root, MapCursor *cursor, bool exactmatch, void *ctx, bool (*callback)(void *, const uint8_t *, uint32_t, bool));
+static void traverseCFBurstTrieCompactMappedLevel(CFBurstTrieRef trie, CompactMapTrieLevelRef root, MapCursor *cursor, bool exactmatch, void *ctx, bool (*callback)(void *, const uint8_t *, uint32_t, bool));
+static void traverseCFBurstTrieWithCursor(CFBurstTrieRef trie, const uint8_t *prefix, uint32_t prefixLen, void **cursor, bool exactmatch, void *ctx, bool (*callback)(void *, const uint8_t *, uint32_t, bool));
+
+static size_t serializeCFBurstTrie(CFBurstTrieRef trie, size_t start_offset, int fd);
+
+static Boolean burstTrieMappedFind(DiskTrieLevelRef trie, char *map, const UInt8 *key, uint32_t length, uint32_t *payload, bool prefix);
+static Boolean burstTrieMappedPageFind(StringPage *page, const UInt8 *key, uint32_t length, uint32_t *payload, bool prefix);
+static Boolean burstTrieCompactTrieMappedFind(CompactDiskTrieLevelRef trie, char *map, const UInt8 *key, uint32_t length, uint32_t *payload, bool prefix);
+
+static void destroyCFBurstTrie(CFBurstTrieRef trie);
+static void finalizeCFBurstTrie(TrieLevelRef trie);
+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 CFIndex burstTrieConvertCharactersToUTF8(UniChar *chars, CFIndex numChars, UInt8 *buffer);
+
+static Boolean advanceMapCursor(CFBurstTrieRef trie, CompactMapCursor *cursor, const UInt8* bytes, CFIndex length);
+static Boolean getMapCursorPayload(CFBurstTrieRef trie, const CompactMapCursor *cursor, uint32_t *payload);
+static void copyMapCursor(const CompactMapCursor *source, CompactMapCursor* destination);
+static Boolean areMapCursorsEqual(const CompactMapCursor *lhs, const CompactMapCursor *rhs);
+static void traverseFromMapCursor(CFBurstTrieRef trie, CompactMapCursor *cursor, UInt8* bytes, uint32_t capacity, uint32_t length, Boolean *stop, void *ctx, CFBurstTrieTraversalCallback callback);
+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));
+ trie->containerSize = MAX_LIST_SIZE;
+
+ CFNumberRef valueAsCFNumber;
+ if (CFDictionaryGetValueIfPresent(options, kCFBurstTrieCreationOptionNameContainerSize, (const void **)&valueAsCFNumber)) {
+ int value;
+ CFNumberGetValue(valueAsCFNumber, kCFNumberIntType, &value);
+ trie->containerSize = value > 2 && value < 4096 ? value : MAX_LIST_SIZE;
+ }
+ trie->retain = 1;
+ return trie;
+}
+
+CFBurstTrieRef CFBurstTrieCreate() {
+ CFBurstTrieRef trie = NULL;
+ int listSize = MAX_LIST_SIZE;
+ CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &listSize);
+ CFMutableDictionaryRef options = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, NULL, NULL);
+ CFDictionarySetValue(options, kCFBurstTrieCreationOptionNameContainerSize, value);
+ trie = CFBurstTrieCreateWithOptions(options);
+ CFRelease(value);
+ CFRelease(options);
+ return trie;
+}
+
+CFBurstTrieRef CFBurstTrieCreateFromFile(CFStringRef path) {
+ struct statinfo sb;
+ char filename[PATH_MAX];
+ int fd;
+
+ /* Check valid path name */
+ if (!CFStringGetCString(path, filename, PATH_MAX, kCFStringEncodingUTF8)) return NULL;
+
+ /* Check if file exists */
+ if (stat(filename, &sb) != 0) return NULL;
+
+ /* Check if file can be opened */
+ if ((fd=open(filename, CF_OPENFLGS|O_RDONLY)) < 0) return NULL;
+
+#if DEPLOYMENT_TARGET_WINDOWS
+ HANDLE mappedFileHandle = (HANDLE)_get_osfhandle(fd);
+ if (!mappedFileHandle) return NULL;
+
+ HANDLE mapHandle = CreateFileMapping(mappedFileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (!mapHandle) return NULL;
+
+ char *map = (char *)MapViewOfFile(mapHandle, FILE_MAP_READ, 0, 0, sb.st_size);
+ if (!map) return NULL;
+#else
+ char *map = mmap(0, sb.st_size, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0);
+#endif
+
+ CFBurstTrieRef trie = NULL;
+ TrieHeader *header = (TrieHeader *)map;
+
+ if (((uint32_t*)map)[0] == 0xbabeface) {
+ trie = (CFBurstTrieRef) calloc(1, sizeof(struct _CFBurstTrie));
+ trie->mapBase = map;
+ trie->mapSize = CFSwapInt32LittleToHost(sb.st_size);
+ trie->mapOffset = CFSwapInt32LittleToHost(((fileHeader*)trie->mapBase)->rootOffset);
+ trie->cflags = CFSwapInt32LittleToHost(((fileHeader*)trie->mapBase)->flags);
+ trie->count = CFSwapInt32LittleToHost(((fileHeader*)trie->mapBase)->count);
+ trie->retain = 1;
+#if DEPLOYMENT_TARGET_WINDOWS
+ trie->mappedFileHandle = mappedFileHandle;
+ trie->mapHandle = mapHandle;
+#else
+ // On Windows, the file being mapped must stay open as long as the map exists. Don't close it early. Other platforms close it here.
+ close(fd);
+#endif
+ } else if (header->signature == 0xcafebabe || header->signature == 0x0ddba11) {
+ trie = (CFBurstTrieRef) calloc(1, sizeof(struct _CFBurstTrie));
+ trie->mapBase = map;
+ trie->mapSize = CFSwapInt32LittleToHost(sb.st_size);
+ trie->cflags = CFSwapInt32LittleToHost(header->flags);
+ trie->count = CFSwapInt32LittleToHost(header->count);
+ trie->retain = 1;
+#if DEPLOYMENT_TARGET_WINDOWS
+ trie->mappedFileHandle = mappedFileHandle;
+ trie->mapHandle = mapHandle;
+#else
+ // On Windows, the file being mapped must stay open as long as the map exists. Don't close it early. Other platforms close it here.
+ close(fd);
+#endif
+ }
+ return trie;
+}
+
+CFBurstTrieRef CFBurstTrieCreateFromMapBytes(char *mapBase) {
+ CFBurstTrieRef trie = NULL;
+ TrieHeader *header = (TrieHeader *)mapBase;
+
+ if (mapBase && ((uint32_t*)mapBase)[0] == 0xbabeface) {
+ trie = (CFBurstTrieRef) malloc(sizeof(struct _CFBurstTrie));
+ trie->mapBase = mapBase;
+ trie->mapSize = CFSwapInt32LittleToHost(((fileHeader*)trie->mapBase)->size);
+ trie->mapOffset = CFSwapInt32LittleToHost(((fileHeader*)trie->mapBase)->rootOffset);
+ trie->cflags = CFSwapInt32LittleToHost(((fileHeader*)trie->mapBase)->flags);
+ trie->count = CFSwapInt32LittleToHost(((fileHeader*)trie->mapBase)->count);
+ trie->retain = 1;
+ } else if (mapBase && (header->signature == 0xcafebabe || header->signature == 0x0ddba11)) {
+ trie = (CFBurstTrieRef) malloc(sizeof(struct _CFBurstTrie));
+ trie->mapBase = mapBase;
+ trie->mapSize = CFSwapInt32LittleToHost(header->size);
+ trie->cflags = CFSwapInt32LittleToHost(header->flags);
+ trie->count = CFSwapInt32LittleToHost(header->count);
+ trie->retain = 1;
+ }
+ return trie;
+}
+
+Boolean CFBurstTrieInsert(CFBurstTrieRef trie, CFStringRef term, CFRange termRange, CFIndex payload) {
+ return CFBurstTrieAddWithWeight(trie, term, termRange, 1, (uint32_t)payload);
+}
+
+Boolean CFBurstTrieAdd(CFBurstTrieRef trie, CFStringRef term, CFRange termRange, uint32_t payload) {
+ return CFBurstTrieAddWithWeight(trie, term, termRange, 1, payload);
+}
+
+Boolean CFBurstTrieInsertCharacters(CFBurstTrieRef trie, UniChar *chars, CFIndex numChars, CFIndex payload) {
+ return CFBurstTrieAddCharactersWithWeight(trie, chars, numChars, 1, (uint32_t)payload);
+}
+
+Boolean CFBurstTrieAddCharacters(CFBurstTrieRef trie, UniChar *chars, CFIndex numChars, uint32_t payload) {
+ return CFBurstTrieAddCharactersWithWeight(trie, chars, numChars, 1, payload);
+}
+
+Boolean CFBurstTrieInsertUTF8String(CFBurstTrieRef trie, UInt8 *chars, CFIndex numChars, CFIndex payload) {
+ return CFBurstTrieAddUTF8StringWithWeight(trie, chars, numChars, 1, (uint32_t)payload);
+}
+
+Boolean CFBurstTrieAddUTF8String(CFBurstTrieRef trie, UInt8 *chars, CFIndex numChars, uint32_t payload) {
+ return CFBurstTrieAddUTF8StringWithWeight(trie, chars, numChars, 1, payload);
+}
+
+Boolean CFBurstTrieInsertWithWeight(CFBurstTrieRef trie, CFStringRef term, CFRange termRange, CFIndex weight, CFIndex payload) {
+ return CFBurstTrieAddWithWeight(trie, term, termRange, weight, (uint32_t)payload);
+}
+
+Boolean CFBurstTrieAddWithWeight(CFBurstTrieRef trie, CFStringRef term, CFRange termRange, uint32_t weight, uint32_t payload) {
+ Boolean success = false;
+ CFIndex size = MAX_STRING_ALLOCATION_SIZE;
+ CFIndex bytesize = termRange.length * 4; //** 4-byte max character size
+ if (!trie->mapBase && termRange.length < MAX_STRING_SIZE && payload > 0) {
+ CFIndex length;
+ UInt8 buffer[MAX_STRING_ALLOCATION_SIZE + 1];
+ UInt8 *key = buffer;
+ if (bytesize >= size) {
+ size = bytesize;
+ key = (UInt8 *) malloc(sizeof(UInt8) * size + 1);
+ }
+ CFStringGetBytes(term, termRange, kCFStringEncodingUTF8, (UInt8)'-', (Boolean)0, key, size, &length);
+ key[length] = 0;
+
+ success = CFBurstTrieAddUTF8StringWithWeight(trie, key, length, weight, payload);
+ if (buffer != key) free(key);
+ }
+ return success;
+}
+
+Boolean CFBurstTrieInsertCharactersWithWeight(CFBurstTrieRef trie, UniChar *chars, CFIndex numChars, CFIndex weight, CFIndex payload) {
+ return CFBurstTrieAddCharactersWithWeight(trie, chars, numChars, weight, (uint32_t)payload);
+}
+
+Boolean CFBurstTrieAddCharactersWithWeight(CFBurstTrieRef trie, UniChar *chars, CFIndex numChars, uint32_t weight, uint32_t payload) {
+ Boolean success = false;
+ CFIndex size = MAX_STRING_ALLOCATION_SIZE;
+ CFIndex bytesize = numChars * 4; //** 4-byte max character size
+ if (!trie->mapBase && numChars < MAX_STRING_SIZE && payload > 0) {
+ CFIndex length;
+ UInt8 buffer[MAX_STRING_ALLOCATION_SIZE + 1];
+ UInt8 *key = buffer;
+ if (bytesize >= size) {
+ size = bytesize;
+ key = (UInt8 *) malloc(sizeof(UInt8) * size + 1);
+ }
+ length = burstTrieConvertCharactersToUTF8(chars, numChars, key);
+ key[length] = 0;
+
+ success = CFBurstTrieAddUTF8StringWithWeight(trie, key, length, weight, payload);
+ if (buffer != key) free(key);
+ }
+ return success;
+}
+
+Boolean CFBurstTrieInsertUTF8StringWithWeight(CFBurstTrieRef trie, UInt8 *chars, CFIndex numChars, CFIndex weight, CFIndex payload) {
+ return CFBurstTrieAddUTF8StringWithWeight(trie, chars, numChars, weight, (uint32_t)payload);
+}
+
+Boolean CFBurstTrieAddUTF8StringWithWeight(CFBurstTrieRef trie, UInt8 *chars, CFIndex numChars, uint32_t weight, uint32_t payload) {
+ CFBTInsertCode code = FailedInsert;
+
+ if (!trie->mapBase && numChars < MAX_STRING_SIZE*4 && payload > 0) {
+ code = addCFBurstTrieLevel(trie, &trie->root, chars, numChars, weight, payload);
+ if (code == NewTerm) trie->count++;
+ }
+ return code > FailedInsert;
+}
+
+Boolean CFBurstTrieFind(CFBurstTrieRef trie, CFStringRef term, CFRange termRange, CFIndex *payload) {
+ uint32_t p;
+ if (CFBurstTrieContains(trie, term, termRange, &p)) {
+ SetPayload(payload, p);
+ return true;
+ }
+ return false;
+}
+
+Boolean CFBurstTrieContains(CFBurstTrieRef trie, CFStringRef term, CFRange termRange, uint32_t *payload) {
+ Boolean success = false;
+ CFIndex size = MAX_STRING_ALLOCATION_SIZE;
+ CFIndex bytesize = termRange.length * 4; //** 4-byte max character size
+ if (termRange.length < MAX_STRING_SIZE) {
+ CFIndex length;
+ UInt8 buffer[MAX_STRING_ALLOCATION_SIZE+1];
+ UInt8 *key = buffer;
+ if (bytesize >= size) {
+ size = bytesize;
+ key = (UInt8 *) malloc(sizeof(UInt8) * size + 1);
+ }
+ CFStringGetBytes(term, termRange, kCFStringEncodingUTF8, (UInt8)'-', (Boolean)0, key, size, &length);
+ key[length] = 0;
+
+ success = CFBurstTrieContainsUTF8String(trie, key, length, payload);
+ if (buffer != key) free(key);
+ }
+ return success;
+}
+
+Boolean CFBurstTrieFindCharacters(CFBurstTrieRef trie, UniChar *chars, CFIndex numChars, CFIndex *payload) {
+ uint32_t p;
+ if (CFBurstTrieContainsCharacters(trie, chars, numChars, &p)) {
+ SetPayload(payload, p);
+ return true;
+ }
+ return false;
+}
+
+Boolean CFBurstTrieContainsCharacters(CFBurstTrieRef trie, UniChar *chars, CFIndex numChars, uint32_t *payload) {
+ Boolean success = false;
+ CFIndex size = MAX_STRING_ALLOCATION_SIZE;
+ CFIndex bytesize = numChars * 4; //** 4-byte max character size
+ if (numChars < MAX_STRING_SIZE) {
+ CFIndex length;
+ UInt8 buffer[MAX_STRING_ALLOCATION_SIZE + 1];
+ UInt8 *key = buffer;
+ if (bytesize >= size) {
+ size = bytesize;
+ key = (UInt8 *) malloc(sizeof(UInt8) * size + 1);
+ }
+ length = burstTrieConvertCharactersToUTF8(chars, numChars, key);
+ key[length] = 0;
+
+ success = CFBurstTrieContainsUTF8String(trie, key, length, payload);
+ if (buffer != key) free(key);
+ }
+ return success;
+}
+
+Boolean CFBurstTrieFindUTF8String(CFBurstTrieRef trie, UInt8 *key, CFIndex length, CFIndex *payload) {
+ uint32_t p;
+ if (CFBurstTrieContainsUTF8String(trie, key, length, &p)) {
+ SetPayload(payload, p);
+ return true;
+ }
+ return false;
+}
+
+Boolean CFBurstTrieContainsUTF8String(CFBurstTrieRef trie, UInt8 *key, CFIndex length, uint32_t *payload) {
+ Boolean success = false;
+ if (length < MAX_STRING_SIZE) {
+ if (trie->mapBase && ((fileHeader *)trie->mapBase)->signature == 0xbabeface) {
+ bool prefix = (trie->cflags & kCFBurstTriePrefixCompression);
+ success = burstTrieMappedFind((DiskTrieLevelRef)(trie->mapBase+CFSwapInt32LittleToHost((((uint32_t*)trie->mapBase)[1]))), trie->mapBase, key, length, payload, prefix);
+ } else if (trie->mapBase && trie->cflags & (kCFBurstTriePrefixCompression | kCFBurstTrieSortByKey)) {
+ _CFBurstTrieCursor cursor;
+ if (!CFBurstTrieSetCursorForBytes(trie, &cursor, key, length))
+ return FALSE;
+ return CFBurstTrieCursorGetPayload(&cursor, payload);
+ } else {
+ uint32_t found = 0;
+ void *cursor = 0;
+ traverseCFBurstTrieWithCursor(trie, key, length, &cursor, true, &found, containsKey);
+ if (found) SetPayload(payload, found);
+ success = found > 0;
+ }
+ }
+ return success;
+}
+
+Boolean CFBurstTrieSerialize(CFBurstTrieRef trie, CFStringRef path, CFBurstTrieOpts opts) {
+ Boolean success = false;
+ if (trie->mapBase) {
+ return success;
+ } else {
+ int fd;
+ char filename[PATH_MAX];
+
+ /* Check valid path name */
+ if (!CFStringGetCString(path, filename, PATH_MAX, kCFStringEncodingUTF8)) return success;
+
+ /* Check if file can be opened */
+ if ((fd=open(filename, CF_OPENFLGS|O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) < 0) return success;
+
+ if (CFBurstTrieSerializeWithFileDescriptor(trie, fd, opts)) success = true;
+
+ close(fd);
+ }
+ return success;
+}
+
+Boolean CFBurstTrieSerializeWithFileDescriptor(CFBurstTrieRef trie, int fd, CFBurstTrieOpts opts) {
+ Boolean success = false;
+ if (!trie->mapBase && fd >= 0) {
+ off_t start_offset = lseek(fd, 0, SEEK_END);
+
+ trie->cflags = opts;
+ trie->mapSize = serializeCFBurstTrie(trie, start_offset, fd);
+
+#if DEPLOYMENT_TARGET_WINDOWS
+ HANDLE mappedFileHandle = (HANDLE)_get_osfhandle(fd);
+ // We need to make sure we have our own handle to keep this file open as long as the mmap lasts
+ DuplicateHandle(GetCurrentProcess(), mappedFileHandle, GetCurrentProcess(), &mappedFileHandle, 0, 0, DUPLICATE_SAME_ACCESS);
+ HANDLE mapHandle = CreateFileMapping(mappedFileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (!mapHandle) return NULL;
+ char *map = (char *)MapViewOfFile(mapHandle, FILE_MAP_READ, 0, start_offset, trie->mapSize);
+ if (!map) return NULL;
+ trie->mapBase = map;
+ trie->mapHandle = mapHandle;
+ trie->mappedFileHandle = mappedFileHandle;
+#else
+ trie->mapBase = mmap(0, trie->mapSize, PROT_READ, MAP_FILE|MAP_SHARED, fd, start_offset);
+#endif
+ success = true;
+ }
+
+ return success;
+}
+
+void CFBurstTrieTraverse(CFBurstTrieRef trie, void *ctx, void (*callback)(void*, const UInt8*, uint32_t, uint32_t)) {
+ TrieHeader *header = (TrieHeader *)trie->mapBase;
+ if (!trie->mapBase || (header->signature == 0xcafebabe || header->signature == 0x0ddba11)) {
+ void *cursor = 0;
+ TraverseContext context;
+ context.context = ctx;
+ context.callback = callback;
+ traverseCFBurstTrieWithCursor(trie, (const uint8_t *)"", 0, &cursor, false, &context, foundKey);
+ }
+}
+
+
+void CFBurstTrieTraverseWithCursor(CFBurstTrieRef trie, const uint8_t *prefix, uint32_t prefixLen, void **cursor, void *ctx, bool (*callback)(void *, const uint8_t *, uint32_t, bool))
+{
+ traverseCFBurstTrieWithCursor(trie, prefix, prefixLen, cursor, false, ctx, callback);
+}
+
+void CFBurstTriePrint(CFBurstTrieRef trie) {
+
+}
+
+CFIndex CFBurstTrieGetCount(CFBurstTrieRef trie) {
+ return trie->count;
+}
+
+CFBurstTrieRef CFBurstTrieRetain(CFBurstTrieRef trie) {
+ trie->retain++;
+ return trie;
+}
+
+void CFBurstTrieRelease(CFBurstTrieRef trie) {
+ trie->retain--;
+ if (trie->retain == 0) destroyCFBurstTrie(trie);
+ return;
+}
+
+Boolean CFBurstTrieSetCursorForBytes(CFBurstTrieRef trie, CFBurstTrieCursorRef cursor, const UInt8* bytes, CFIndex length)
+{
+ if (!trie->mapBase || !(trie->cflags & (kCFBurstTriePrefixCompression | kCFBurstTrieSortByKey))) {
+ //fprintf(stderr, "CFBurstTrieCreateCursorForBytes() only support file based trie in prefix compression format.\n");
+ return FALSE;
+ }
+
+ TrieHeader *header = (TrieHeader*)trie->mapBase;
+ if (length < 0 || !trie)
+ return FALSE;
+
+ cursor->trie = trie;
+ if (trie->mapBase) {
+ cursor->cursorType = _kCFBurstTrieCursorMapType;
+ cursor->mapCursor.next = header->rootOffset;
+ cursor->mapCursor.isOnPage = FALSE;
+ cursor->mapCursor.entryOffsetInPage = 0;
+ cursor->mapCursor.offsetInEntry = 0;
+ cursor->mapCursor.payload = 0;
+ } else
+ assert(false);
+
+ if (!bytes || length == 0)
+ return TRUE;
+
+ return CFBurstTrieCursorAdvanceForBytes(cursor, bytes, length);
+}
+
+
+CFBurstTrieCursorRef CFBurstTrieCreateCursorForBytes(CFBurstTrieRef trie, const UInt8* bytes, CFIndex length)
+{
+ CFBurstTrieCursorRef cursor = (CFBurstTrieCursorRef)calloc(sizeof(_CFBurstTrieCursor), 1);
+ if (!CFBurstTrieSetCursorForBytes(trie, cursor, bytes, length)) {
+ CFBurstTrieCursorRelease(cursor);
+ return NULL;
+ }
+ return cursor;
+}
+
+CFBurstTrieCursorRef CFBurstTrieCursorCreateByCopy(CFBurstTrieCursorRef cursor)
+{
+ if (!cursor)
+ return NULL;
+
+ CFBurstTrieCursorRef newCursor = (CFBurstTrieCursorRef)calloc(sizeof(_CFBurstTrieCursor), 1);
+ switch (cursor->cursorType) {
+ case _kCFBurstTrieCursorMapType:
+ copyMapCursor(&cursor->mapCursor, &newCursor->mapCursor);
+ break;
+ case _kCFBurstTrieCursorTrieType:
+ assert(false);
+ break;
+ }
+ newCursor->cursorType = cursor->cursorType;
+ newCursor->trie = cursor->trie;
+ return newCursor;
+}
+
+Boolean CFBurstTrieCursorIsEqual(CFBurstTrieCursorRef lhs, CFBurstTrieCursorRef rhs)
+{
+ if (lhs->trie != rhs->trie || lhs->cursorType != rhs->cursorType)
+ return FALSE;
+
+ if (lhs->cursorType == _kCFBurstTrieCursorMapType)
+ return areMapCursorsEqual(&lhs->mapCursor, &rhs->mapCursor);
+ else
+ return FALSE;
+}
+
+Boolean CFBurstTrieCursorAdvanceForBytes(CFBurstTrieCursorRef cursor, const UInt8* bytes, CFIndex length)
+{
+ switch (cursor->cursorType) {
+ case _kCFBurstTrieCursorMapType: {
+ CompactMapCursor tempCursor;
+ copyMapCursor(&cursor->mapCursor, &tempCursor);
+ if (advanceMapCursor(cursor->trie, (CompactMapCursor*)&cursor->mapCursor, bytes, length))
+ return TRUE;
+ else {
+ copyMapCursor(&tempCursor, &cursor->mapCursor);
+ return FALSE;
+ }
+ }
+ case _kCFBurstTrieCursorTrieType:
+ return FALSE;
+ }
+ return FALSE;
+}
+
+Boolean CFBurstTrieCursorGetPayload(CFBurstTrieCursorRef cursor, uint32_t *payload)
+{
+ switch (cursor->cursorType) {
+ case _kCFBurstTrieCursorMapType:
+ return getMapCursorPayload(cursor->trie, (CompactMapCursor*)&cursor->mapCursor, payload);
+ case _kCFBurstTrieCursorTrieType:
+ return FALSE;
+ }
+ return FALSE;
+}
+
+void CFBurstTrieCursorRelease(CFBurstTrieCursorRef cursor)
+{
+ if (!cursor)
+ return;
+ free(cursor);
+}
+
+void CFBurstTrieTraverseFromCursor(CFBurstTrieCursorRef cursor, void *ctx, CFBurstTrieTraversalCallback callback)
+{
+ if (!cursor)
+ return;
+
+ UInt8 *bytes = (UInt8*)calloc(1, MAX_KEY_LENGTH);
+ uint32_t capacity = MAX_KEY_LENGTH;
+ uint32_t length = 0;
+ Boolean stop = FALSE;
+ switch (cursor->cursorType) {
+ case _kCFBurstTrieCursorMapType: {
+ CompactMapCursor tempCursor;
+ copyMapCursor(&cursor->mapCursor, &tempCursor);
+ traverseFromMapCursor(cursor->trie, &tempCursor, bytes, capacity,length, &stop, ctx, callback);
+ break;
+ }
+ case _kCFBurstTrieCursorTrieType:
+ break;
+ }
+ free(bytes);
+}
+
+#if 0
+#pragma mark -
+#pragma mark Insertion
+#endif
+
+static ListNodeRef makeCFBurstTrieListNode(const uint8_t *key, uint32_t keylen, uint32_t weight, uint32_t payload) {
+ ListNodeRef node = (ListNodeRef) calloc(1, sizeof(*node) + keylen + 1);
+ memcpy(node->string, key, keylen);
+ node->string[keylen] = 0;
+ node->next = 0;
+ node->length = keylen;
+ node->weight = weight;
+ node->payload = payload;
+ return node;
+}
+
+static void addCFBurstTrieBurstLevel(CFBurstTrieRef trie, TrieLevelRef root, const uint8_t *key, uint32_t keylen, uint32_t weight, uint32_t payload) {
+ if (keylen) {
+ NextTrie next = root->slots[*key];
+ ListNodeRef newNode = makeCFBurstTrieListNode(key+1, keylen-1, weight, payload);
+ newNode->weight = weight;
+ newNode->next = (ListNodeRef) NextTrie_GetPtr(next);
+ next = (uintptr_t) newNode;
+ NextTrie_SetKind(next, ListKind);
+ root->slots[*key] = next;
+ } else {
+ // ** Handle payload.
+ root->weight = weight;
+ root->payload = payload;
+ }
+}
+
+static TrieLevelRef burstCFBurstTrieLevel(CFBurstTrieRef trie, ListNodeRef list, uint32_t listCount) {
+ TrieLevelRef newLevel = (TrieLevelRef) calloc(1, sizeof(struct _TrieLevel));
+ while (list) {
+ addCFBurstTrieBurstLevel(trie, newLevel, list->string, list->length, list->weight, list->payload);
+ ListNodeRef temp = list;
+ list = list->next;
+ free(temp);
+ }
+ return newLevel;
+}
+
+static CFBTInsertCode addCFBurstTrieListNode(CFBurstTrieRef trie, ListNodeRef list, const uint8_t *key, uint32_t keylen, uint32_t weight, uint32_t payload, uint32_t *listCount)
+{
+ CFBTInsertCode code = FailedInsert;
+ uint32_t count = 1;
+
+ ListNodeRef last = list;
+ while (list) {
+ if (list->length == keylen && memcmp(key, list->string, keylen) == 0) {
+ list->weight += weight;
+ list->payload = payload;
+ code = ExistingTerm;
+ break;
+ } else {
+ count++;
+ last = list;
+ list = list->next;
+ }
+ }
+
+ if (!list) {
+ last->next = makeCFBurstTrieListNode(key, keylen, weight, payload);
+ code = NewTerm;
+ }
+
+ *listCount = count;
+ return code;
+}
+
+static CFBTInsertCode addCFBurstTrieLevel(CFBurstTrieRef trie, TrieLevelRef root, const uint8_t *key, uint32_t keylen, uint32_t weight, uint32_t payload)
+{
+ CFBTInsertCode code = FailedInsert;
+ if (keylen) {
+ NextTrie next = root->slots[*key];
+ if (NextTrie_GetKind(next) == TrieKind) {
+ TrieLevelRef nextLevel = (TrieLevelRef) NextTrie_GetPtr(next);
+ code = addCFBurstTrieLevel(trie, nextLevel, key+1, keylen-1, weight, payload);
+ } else {
+ if (NextTrie_GetKind(next) == ListKind) {
+ uint32_t listCount;
+ ListNodeRef listNode = (ListNodeRef) NextTrie_GetPtr(next);
+ code = addCFBurstTrieListNode(trie, listNode, key+1, keylen-1, weight, payload, &listCount);
+ if (listCount > trie->containerSize) {
+ next = (uintptr_t) burstCFBurstTrieLevel(trie, listNode, listCount);
+ NextTrie_SetKind(next, TrieKind);
+ }
+ } else {
+ // ** Make a new list node
+ next = (uintptr_t) makeCFBurstTrieListNode(key+1, keylen-1, weight, payload);
+ NextTrie_SetKind(next, ListKind);
+ code = NewTerm;
+ }
+ root->slots[*key] = next;
+ }
+ } else {
+ // ** Handle payload
+ if (!root->weight) code = NewTerm;
+ else code = ExistingTerm;
+ root->weight += weight;
+ root->payload = payload;
+ }
+
+ return code;
+}
+#if 0
+#pragma mark -
+#pragma mark Searching
+#endif
+static void findCFBurstTrieList(CFBurstTrieRef trie, TrieCursor *cursor, void *ctx, bool (*callback)(void*, const uint8_t*, uint32_t, bool))
+{
+ ListNodeRef list = (ListNodeRef)NextTrie_GetPtr(cursor->next);
+ int len = cursor->prefixlen-cursor->keylen;
+ len = len <= 0 ? 0 : len;
+ while (list) {
+ int lencompare = list->length-len;
+ if (list->length >= len &&
+ (len == 0 || memcmp(list->string, cursor->prefix+cursor->keylen, len) == 0)) {
+ memcpy(cursor->key+cursor->keylen, list->string, list->length);
+ cursor->key[cursor->keylen+list->length] = 0;
+ cursor->next = (NextTrie)list;
+ if (list->payload && callback(ctx, cursor->key, list->payload, lencompare==0)) return;
+ }
+ list = list->next;
+ }
+}
+
+static void findCFBurstTrieMappedPage(CFBurstTrieRef trie, MapCursor *cursor, void *ctx, bool (*callback)(void*, const uint8_t*, uint32_t, bool))
+{
+ Page *page = (Page *)DiskNextTrie_GetPtr(trie->mapBase, cursor->next);
+ uint32_t end = page->length;
+ uint32_t cur = 0;
+ int len = cursor->prefixlen-cursor->keylen;
+ len = len <= 0 ? 0 : len;
+ if (trie->cflags & kCFBurstTriePrefixCompression) {
+ uint8_t pfx[CHARACTER_SET_SIZE];
+ PageEntryPacked *lastEntry = 0;
+ while (cur < end) {
+ PageEntryPacked *entry = (PageEntryPacked *)&page->data[cur];
+ int lencompare = (entry->strlen+entry->pfxLen)-len;
+ if (lastEntry && entry->pfxLen>lastEntry->pfxLen) memcpy(pfx+lastEntry->pfxLen, lastEntry->string, entry->pfxLen-lastEntry->pfxLen);
+ if (lencompare >= 0 &&
+ (len == 0 || (__builtin_memcmp(pfx, cursor->prefix+cursor->keylen, entry->pfxLen) == 0 &&
+ __builtin_memcmp(entry->string, cursor->prefix+cursor->keylen+entry->pfxLen, cursor->prefixlen-cursor->keylen-entry->pfxLen) == 0))) {
+ memcpy(cursor->key+cursor->keylen, pfx, entry->pfxLen);
+ memcpy(cursor->key+cursor->keylen+entry->pfxLen, entry->string, entry->strlen);
+ cursor->key[cursor->keylen+entry->pfxLen+entry->strlen] = 0;
+ if (entry->payload && callback(ctx, (const uint8_t *)cursor->key, entry->payload, lencompare==0)) return;
+ }
+ lastEntry = entry;
+ cur += sizeof(*entry) + entry->strlen;
+ }
+ } else {
+ while (cur < end) {
+ PageEntry *entry = (PageEntry *)&page->data[cur];
+ int lencompare = entry->strlen-len;
+ if (lencompare >= 0 && __builtin_memcmp(entry->string, cursor->prefix+cursor->keylen, len) == 0) {
+ memcpy(cursor->key+cursor->keylen, entry->string, entry->strlen);
+ cursor->key[cursor->keylen+entry->strlen] = 0;
+ if (entry->payload && callback(ctx, (const uint8_t *)cursor->key, entry->payload, lencompare==0)) return;
+ }
+ cur += sizeof(*entry) + entry->strlen;
+ }
+ }
+}
+
+
+static void findCFBurstTrieLevel(CFBurstTrieRef trie, TrieCursor *cursor, bool exactmatch, void *ctx, bool (*callback)(void*, const uint8_t*, uint32_t, bool))
+{
+ if (cursor->keylen < cursor->prefixlen) {
+ cursor->next = ((TrieLevelRef)NextTrie_GetPtr(cursor->next))->slots[cursor->prefix[cursor->keylen]];
+ cursor->key[cursor->keylen++] = cursor->prefix[cursor->keylen];
+
+ if (NextTrie_GetKind(cursor->next) == TrieKind) {
+ findCFBurstTrieLevel(trie, cursor, exactmatch, ctx, callback);
+ } else if (NextTrie_GetKind(cursor->next) == ListKind) {
+ findCFBurstTrieList(trie, cursor, ctx, callback);
+ }
+ } else {
+ TrieLevelRef root = (TrieLevelRef)NextTrie_GetPtr(cursor->next);
+ if (root->payload && callback(ctx, cursor->key, root->payload, cursor->prefixlen==cursor->keylen)) return;
+ if (cursor->keylen == cursor->prefixlen && exactmatch) return;
+ traverseCFBurstTrieLevel(trie, root, cursor, exactmatch, ctx, callback);
+ }
+}
+
+static void findCFBurstTrieCompactMappedLevel(CFBurstTrieRef trie, MapCursor *cursor, bool exactmatch, void *ctx, bool (*callback)(void*, const uint8_t*, uint32_t, bool))
+{
+ CompactMapTrieLevelRef root = (CompactMapTrieLevelRef)DiskNextTrie_GetPtr(trie->mapBase, cursor->next);
+ if (cursor->keylen < cursor->prefixlen) {
+ uint8_t mykey = *(cursor->prefix+cursor->keylen);
+ cursor->key[cursor->keylen++] = *(cursor->prefix+cursor->keylen);
+
+ uint8_t slot = mykey / 64;
+ uint8_t bit = mykey % 64;
+ uint32_t item = 0;
+ uint64_t bword = root->bitmap[slot];
+
+ if (bword & (1ull << bit)) {
+ // ** Count all the set bits up to this bit
+ for (int i=0; i < slot; i++) item += __builtin_popcountll(root->bitmap[i]);
+ item += __builtin_popcountll(bword & ((1ull << bit)-1));
+ uint32_t offset = root->slots[item];
+ cursor->next = offset;
+
+ if (DiskNextTrie_GetKind(offset) == TrieKind) {
+ findCFBurstTrieMappedLevel(trie, cursor, exactmatch, ctx, callback);
+ } else if (DiskNextTrie_GetKind(offset) == CompactTrieKind) {
+ findCFBurstTrieCompactMappedLevel(trie, cursor, exactmatch, ctx, callback);
+ } else if (DiskNextTrie_GetKind(offset) == ListKind) {
+ findCFBurstTrieMappedPage(trie, cursor, ctx, callback);
+ }
+ }
+ } else {
+ if(root->payload && callback(ctx, cursor->key, root->payload, cursor->prefixlen==cursor->keylen)) return;
+ if (cursor->keylen == cursor->prefixlen && exactmatch) return;
+ traverseCFBurstTrieCompactMappedLevel(trie, root, cursor, exactmatch, ctx, callback);
+ }
+}
+
+static void findCFBurstTrieMappedLevel(CFBurstTrieRef trie, MapCursor *cursor, bool exactmatch, void *ctx, bool (*callback)(void*, const uint8_t*, uint32_t, bool))
+{
+ MapTrieLevelRef root = (MapTrieLevelRef)DiskNextTrie_GetPtr(trie->mapBase, cursor->next);
+ if (cursor->keylen < cursor->prefixlen) {
+ uint8_t slot = *(cursor->prefix+cursor->keylen);
+ cursor->next = root->slots[slot];
+ cursor->key[cursor->keylen++] = slot;
+
+ if (DiskNextTrie_GetKind(cursor->next) == TrieKind) {
+ findCFBurstTrieMappedLevel(trie, cursor, exactmatch, ctx, callback);
+ } else if (DiskNextTrie_GetKind(cursor->next) == CompactTrieKind) {
+ findCFBurstTrieCompactMappedLevel(trie, cursor, exactmatch, ctx, callback);
+ } else if (DiskNextTrie_GetKind(cursor->next) == ListKind) {
+ findCFBurstTrieMappedPage(trie, cursor, ctx, callback);
+ }
+ } else {
+ if (root->payload && callback(ctx, cursor->key, root->payload, cursor->prefixlen==cursor->keylen)) return;
+ if (cursor->keylen == cursor->prefixlen && exactmatch) return;
+ traverseCFBurstTrieMappedLevel(trie, root, cursor, exactmatch, ctx, callback);
+ }
+}
+
+static void traverseCFBurstTrieLevel(CFBurstTrieRef trie, TrieLevelRef root, TrieCursor *cursor, bool exactmatch, void *ctx, bool (*callback)(void *, const uint8_t *, uint32_t, bool))
+{
+ cursor->key[cursor->keylen] = 0;
+ uint32_t len = cursor->keylen;
+ for (int i=0; i < CHARACTER_SET_SIZE; i++) {
+ NextTrie next = root->slots[i];
+ cursor->keylen = len;
+ cursor->key[cursor->keylen++] = i;
+
+ if (NextTrie_GetKind(next) == TrieKind) {
+ TrieLevelRef level = (TrieLevelRef)NextTrie_GetPtr(next);
+ if (level->payload && callback(ctx, cursor->key, level->payload, cursor->prefixlen==cursor->keylen)) return;
+ if (cursor->keylen == cursor->prefixlen && exactmatch) return;
+ traverseCFBurstTrieLevel(trie, level, cursor, exactmatch, ctx, callback);
+ } else if (NextTrie_GetKind(next) == ListKind) {
+ cursor->next = next;
+ cursor->key[cursor->keylen] = 0;
+ findCFBurstTrieList(trie, cursor, ctx, callback);
+ }
+ }
+}
+
+static void traverseCFBurstTrieMappedLevel(CFBurstTrieRef trie, MapTrieLevelRef root, MapCursor *cursor, bool exactmatch, void *ctx, bool (*callback)(void *, const uint8_t *, uint32_t, bool))
+{
+ cursor->key[cursor->keylen] = 0;
+ uint32_t len = cursor->keylen;
+
+ for (int i=0; i < CHARACTER_SET_SIZE; i++) {
+ uint32_t offset = (uint32_t)root->slots[i];
+ cursor->keylen = len;
+ cursor->key[cursor->keylen++] = i;
+
+ if (DiskNextTrie_GetKind(offset) == TrieKind) {
+ MapTrieLevelRef level = (MapTrieLevelRef)DiskNextTrie_GetPtr(trie->mapBase, offset);
+ if (level->payload && callback(ctx, cursor->key, level->payload, cursor->prefixlen==cursor->keylen)) return;
+ if (cursor->keylen == cursor->prefixlen && exactmatch) return;
+ traverseCFBurstTrieMappedLevel(trie, level, cursor, exactmatch, ctx, callback);
+ } else if (DiskNextTrie_GetKind(offset) == CompactTrieKind) {
+ CompactMapTrieLevelRef level = (CompactMapTrieLevelRef)DiskNextTrie_GetPtr(trie->mapBase, offset);
+ if (level->payload && callback(ctx, cursor->key, level->payload, cursor->prefixlen==cursor->keylen)) return;
+ if (cursor->keylen == cursor->prefixlen && exactmatch) return;
+ traverseCFBurstTrieCompactMappedLevel(trie, level, cursor, exactmatch, ctx, callback);
+ } else if (DiskNextTrie_GetKind(offset) == ListKind) {
+ cursor->next = offset;
+ cursor->key[cursor->keylen] = 0;
+ findCFBurstTrieMappedPage(trie, cursor, ctx, callback);
+ }
+ }
+}
+
+static void traverseCFBurstTrieCompactMappedLevel(CFBurstTrieRef trie, CompactMapTrieLevelRef root, MapCursor *cursor, bool exactmatch, void *ctx, bool (*callback)(void *, const uint8_t *, uint32_t, bool))
+{
+ cursor->key[cursor->keylen] = 0;
+ uint32_t len = cursor->keylen;
+ for (uint32_t c=0; c < CHARACTER_SET_SIZE; c++) {
+ //** This could be optimized to remember what the last slot/item was and not count bits over and over.
+ uint8_t mykey = c;
+ uint32_t slot = mykey / 64;
+ uint32_t bit = mykey % 64;
+ uint32_t item = 0;
+ uint64_t bword = root->bitmap[slot];
+ cursor->keylen = len;
+
+ if (bword & (1ull << bit)) {
+ // ** Count all the set bits up to this bit
+ for (int i=0; i < slot; i++) item += __builtin_popcountll(root->bitmap[i]);
+ item += __builtin_popcountll(bword & ((1ull << bit)-1));
+ uint32_t offset = root->slots[item];
+ cursor->key[cursor->keylen++] = mykey;
+
+ if(DiskNextTrie_GetKind(offset) == CompactTrieKind) {
+ CompactMapTrieLevelRef level = (CompactMapTrieLevelRef)DiskNextTrie_GetPtr(trie->mapBase, offset);
+ if (level->payload && callback(ctx, cursor->key, level->payload, cursor->prefixlen==cursor->keylen)) return;
+ if (cursor->keylen == cursor->prefixlen && exactmatch) return;
+ traverseCFBurstTrieCompactMappedLevel(trie, level, cursor, exactmatch, ctx, callback);
+ } else if(DiskNextTrie_GetKind(offset) == TrieKind) {
+ traverseCFBurstTrieMappedLevel(trie, (MapTrieLevelRef)DiskNextTrie_GetPtr(trie->mapBase, offset), cursor, exactmatch, ctx, callback);
+ } else if (DiskNextTrie_GetKind(offset) == ListKind) {
+ cursor->next = offset;
+ cursor->key[cursor->keylen] = 0;
+ findCFBurstTrieMappedPage(trie, cursor, ctx, callback);
+ }
+ }
+ }
+}
+
+static void traverseCFBurstTrieWithCursor(CFBurstTrieRef trie, const uint8_t *prefix, uint32_t prefixLen, void **cursor, bool exactmatch, void *ctx, bool (*callback)(void *, const uint8_t *, uint32_t, bool)) {
+ if (trie->mapBase) {
+ if (trie->cflags & kCFBurstTriePrefixCompression) {
+ fprintf(stderr, "Please use CFBurstTrieCursorRef API for file based trie.\n");
+ return;
+ } else {
+ TrieHeader *header = (TrieHeader *)trie->mapBase;
+ MapCursor csr;
+ csr.next = header->rootOffset;
+ csr.prefix = prefix;
+ csr.prefixlen = prefixLen;
+ csr.key[0] = 0;
+ csr.keylen = 0;
+ findCFBurstTrieMappedLevel(trie, &csr, exactmatch, ctx, callback);
+ }
+ } else {
+ TrieCursor csr;
+ csr.next = ((unsigned long)&trie->root)|TrieKind;
+ csr.prefix = prefix;
+ csr.prefixlen = prefixLen;
+ csr.key[0] = 0;
+ csr.keylen = 0;
+ findCFBurstTrieLevel(trie, &csr, exactmatch, ctx, callback);
+ }
+}
+
+CF_INLINE uint32_t getPackedPageEntrySize(PageEntryPacked *entry)
+{
+ return sizeof(PageEntryPacked) + entry->strlen;
+}
+
+CF_INLINE uint32_t getPageEntrySize(PageEntry *entry)
+{
+ return sizeof(PageEntry) + entry->strlen;
+}
+
+/*
+static void _printPageEntry(PageEntryPacked *entry) {
+ printf("entry 0x%p:\n", entry);
+ printf("pfxLen = %d, strLen = %d\n", entry->pfxLen, entry->strlen);
+ if (entry->strlen > 0) {
+ printf("string = ");
+ for (int i = 0; i < entry->strlen; ++i)
+ printf("%d ", entry->string[i]);
+ printf("\n");
+ }
+ printf("\n");
+}
+*/
+static Boolean advanceCursorOnMappedPageForByte(Page *page, CompactMapCursor *cursor, UInt8 byte) {
+ PageEntryPacked *entry;
+ Boolean found = FALSE;
+ uint32_t minPrefixLength = 0;
+
+ if (cursor->isOnPage) {
+ entry = (PageEntryPacked *)&page->data[cursor->entryOffsetInPage];
+ //_printPageEntry(entry);
+ BOOL shouldContinue = TRUE;
+
+ if (!(cursor->entryOffsetInPage == 0 && entry->strlen == 0)) {
+ if (cursor->entryOffsetInPage == entry->strlen - 1) {
+ minPrefixLength = entry->pfxLen + entry->strlen;
+ cursor->entryOffsetInPage += getPackedPageEntrySize(entry);
+ } else {
+ cursor->offsetInEntry++;
+ if (entry->string[cursor->offsetInEntry] == byte)
+ found = TRUE;
+ else if (entry->string[cursor->offsetInEntry] > byte)
+ shouldContinue = FALSE;
+ else {
+ minPrefixLength = entry->pfxLen + cursor->offsetInEntry;
+ cursor->entryOffsetInPage += getPackedPageEntrySize(entry);
+ }
+ }
+ }
+
+ if (found) {
+ cursor->isOnPage = TRUE;
+ return TRUE;
+ } else if (!shouldContinue)
+ return FALSE;
+ } else {
+ cursor->entryOffsetInPage = 0;
+ }
+
+ uint32_t pageSize = page->length - sizeof(Page);
+ while (cursor->entryOffsetInPage < pageSize) {
+ entry = (PageEntryPacked *)&page->data[cursor->entryOffsetInPage];
+ //_printPageEntry(entry);
+ if (minPrefixLength > entry->pfxLen)
+ break;
+ else if (minPrefixLength < entry->pfxLen)
+ cursor->entryOffsetInPage += getPackedPageEntrySize(entry);
+ else {
+ if (entry->strlen == 0)
+ cursor->entryOffsetInPage += getPackedPageEntrySize(entry);
+ else {
+ if (entry->string[0] > byte)
+ // Entries are sorted alphabetically
+ break;
+ else if (entry->string[0] < byte)
+ cursor->entryOffsetInPage += getPackedPageEntrySize(entry);
+ else {
+ cursor->offsetInEntry = 0;
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ if (found)
+ cursor->isOnPage = TRUE;
+
+ return found;
+}
+
+static Boolean advanceCursorMappedPageWithPerfixCompression(Page *page, CompactMapCursor *cursor, const UInt8* bytes, CFIndex length)
+{
+ if (length == 0) {
+ PageEntryPacked *entry = (PageEntryPacked*)&page->data[0];
+ if (!cursor->isOnPage) {
+ cursor->entryOffsetInPage = 0;
+ cursor->offsetInEntry = 0;
+ cursor->isOnPage = entry->pfxLen == 0 && entry->strlen == 0;
+ }
+ getMapCursorPayloadFromPackedPageEntry(entry, cursor, &cursor->payload);
+ return TRUE;
+ }
+
+ for (CFIndex i = 0; i < length; ++i) {
+ if (!advanceCursorOnMappedPageForByte(page, cursor, bytes[i]))
+ return FALSE;
+ }
+ PageEntryPacked *entry = (PageEntryPacked*)&page->data[cursor->entryOffsetInPage];
+ getMapCursorPayloadFromPackedPageEntry(entry, cursor, &cursor->payload);
+ return TRUE;
+}
+
+static Boolean advanceCursorMappedPageSortedByKey(Page *page, CompactMapCursor *cursor, const UInt8* bytes, CFIndex length)
+{
+ if (length == 0) {
+ PageEntry*entry = (PageEntry*)&page->data[0];
+ if (!cursor->isOnPage) {
+ cursor->entryOffsetInPage = 0;
+ cursor->offsetInEntry = 0;
+ cursor->isOnPage = entry->strlen == 0;
+ }
+ getMapCursorPayloadFromPageEntry(entry, cursor, &cursor->payload);
+ return TRUE;
+ }
+
+ PageEntry *entry;
+ uint32_t pageSize = page->length - sizeof(Page);
+ const UInt8 * prefix = NULL;
+ uint32_t prefixLength = 0;
+
+ if (cursor->isOnPage) {
+ entry = (PageEntry*)&page->data[cursor->entryOffsetInPage];
+ prefix = entry->string;
+ prefixLength = cursor->offsetInEntry + 1;
+ }
+
+ while (cursor->entryOffsetInPage < pageSize) {
+ PageEntry *entry = (PageEntry*)&page->data[cursor->entryOffsetInPage];
+ if (entry->strlen == 0) {
+ cursor->entryOffsetInPage += getPageEntrySize(entry);
+ continue;
+ }
+
+ if (entry->strlen <= prefixLength)
+ return FALSE;
+ else {
+ int cmpResult = 0;
+ if (prefixLength > 0)
+ cmpResult = __builtin_memcmp(entry->string, prefix, prefixLength);
+ if (cmpResult > 0)
+ return FALSE;
+ else if (cmpResult == 0) {
+ if (entry->strlen < prefixLength + length) {
+ int cmpResult2 = __builtin_memcmp(entry->string + prefixLength, bytes, entry->strlen - prefixLength);
+ if (cmpResult2 > 0)
+ return FALSE;
+ else
+ cursor->entryOffsetInPage += getPageEntrySize(entry);
+ } else {
+ int cmpResult2 = __builtin_memcmp(entry->string + prefixLength, bytes, length);
+ if (cmpResult2 > 0)
+ return FALSE;
+ else if (cmpResult2 == 0) {
+ cursor->isOnPage = TRUE;
+ cursor->offsetInEntry = prefixLength + length - 1;
+ getMapCursorPayloadFromPageEntry(entry, cursor, &cursor->payload);
+ return TRUE;
+ } else
+ cursor->entryOffsetInPage += getPageEntrySize(entry);
+ }
+ } else
+ cursor->entryOffsetInPage += getPageEntrySize(entry);
+ }
+ }
+ return FALSE;
+}
+
+static Boolean advanceCursorMappedPage(CFBurstTrieRef trie, CompactMapCursor *cursor, const UInt8* bytes, CFIndex length)
+{
+ if (!bytes || length < 0)
+ return FALSE;
+
+ Page *page = (Page *)DiskNextTrie_GetPtr(trie->mapBase, cursor->next);
+ uint32_t pageSize = page->length - sizeof(Page);
+ if (pageSize == 0)
+ return FALSE;
+
+ if (trie->cflags & kCFBurstTrieSortByKey)
+ return advanceCursorMappedPageSortedByKey(page, cursor, bytes, length);
+ else if (trie->cflags & kCFBurstTriePrefixCompression)
+ return advanceCursorMappedPageWithPerfixCompression(page, cursor, bytes, length);
+ else
+ return FALSE;
+}
+
+static Boolean advanceCursorCompactMappedLevel(CFBurstTrieRef trie, CompactMapCursor *cursor, const UInt8* bytes, CFIndex length)
+{
+ if (!bytes || length < 0)
+ return FALSE;
+
+ CompactMapTrieLevelRef root = (CompactMapTrieLevelRef)DiskNextTrie_GetPtr(trie->mapBase, cursor->next);
+ if (length == 0) {
+ cursor->payload = root->payload;
+ return TRUE;
+ }
+
+ uint8_t slot = bytes[0] / 64;
+ uint8_t bit = bytes[0] % 64;
+ uint32_t item = 0;
+ uint64_t bword = root->bitmap[slot];
+ if (bword & (1ull << bit)) {
+ // Count all the set bits up to this bit
+ for (int i = 0; i < slot; ++i)
+ item += __builtin_popcountll(root->bitmap[i]);
+ item += __builtin_popcountll(bword & ((1ull << bit)-1));
+ cursor->next = root->slots[item];
+ return advanceMapCursor(trie, cursor, bytes + 1, length - 1);
+ } else {
+ return FALSE;
+ }
+}
+
+static Boolean advanceCursorMappedLevel(CFBurstTrieRef trie, CompactMapCursor *cursor, const UInt8* bytes, CFIndex length)
+{
+ if (!bytes || length < 0)
+ return FALSE;
+
+ MapTrieLevelRef root = (MapTrieLevelRef)DiskNextTrie_GetPtr(trie->mapBase, cursor->next);
+ if (length == 0) {
+ cursor->payload = root->payload;
+ return TRUE;
+ }
+
+ cursor->next = root->slots[bytes[0]];
+ return advanceMapCursor(trie, cursor, bytes + 1, length - 1);
+}
+
+static Boolean advanceMapCursor(CFBurstTrieRef trie, CompactMapCursor *cursor, const UInt8* bytes, CFIndex length)
+{
+ bool result = FALSE;
+ switch (DiskNextTrie_GetKind(cursor->next)) {
+ case TrieKind:
+ result = advanceCursorMappedLevel(trie, cursor, bytes, length);
+ break;
+ case CompactTrieKind:
+ result = advanceCursorCompactMappedLevel(trie, cursor, bytes, length);
+ break;
+ case ListKind:
+ result = advanceCursorMappedPage(trie, cursor, bytes, length);
+ break;
+ case Nothing: {
+ TrieHeader *header = (TrieHeader*)trie->mapBase;
+ if (cursor->next == header->rootOffset)
+ result = advanceCursorMappedLevel(trie, cursor, bytes, length);
+ }
+ }
+
+ return result;
+}
+
+static void traverseFromMapCursorMappedLevel(CFBurstTrieRef trie, CompactMapCursor *cursor, UInt8* bytes, uint32_t capacity, uint32_t length, Boolean *stop, void *ctx, CFBurstTrieTraversalCallback callback)
+{
+ MapTrieLevelRef root = (MapTrieLevelRef)DiskNextTrie_GetPtr(trie->mapBase, cursor->next);
+ if (root->payload) {
+ callback(ctx, bytes, length, root->payload, stop);
+ if (*stop)
+ return;
+ }
+
+ if (length >= capacity)
+ return;
+
+ for (int i = 0; i < CHARACTER_SET_SIZE; ++i) {i =
+ bytes[length] = i;
+ cursor->next = (uint32_t)root->slots[i];;
+ cursor->isOnPage = FALSE;
+ cursor->entryOffsetInPage = 0;
+ cursor->offsetInEntry = 0;
+ cursor->payload = 0;
+ traverseFromMapCursor(trie, cursor, bytes, capacity - 1, length + 1, stop, ctx, callback);
+ if (*stop)
+ return;
+ }
+}
+
+static void traverseFromMapCursorCompactMappedLevel(CFBurstTrieRef trie, CompactMapCursor *cursor, UInt8* bytes, uint32_t capacity, uint32_t length, Boolean *stop, void *ctx, CFBurstTrieTraversalCallback callback)
+{
+ CompactMapTrieLevelRef root = (CompactMapTrieLevelRef)DiskNextTrie_GetPtr(trie->mapBase, cursor->next);
+ if (root->payload) {
+ callback(ctx, bytes, length, root->payload, stop);
+ if (*stop)
+ return;
+ }
+
+ if (length >= capacity)
+ return;
+ for (int c = 0; c < CHARACTER_SET_SIZE; ++c) {
+ bytes[length] = c;
+ //This could be optimized to remember what the last slot/item was and not count bits over and over.
+ uint8_t slot = c / 64;
+ uint8_t bit = c % 64;
+ uint32_t item = 0;
+ uint64_t bword = root->bitmap[slot];
+ if (bword & (1ull << bit)) {
+ // Count all the set bits up to this bit
+ for (int i = 0; i < slot; ++i)
+ item += __builtin_popcountll(root->bitmap[i]);
+ item += __builtin_popcountll(bword & ((1ull << bit)-1));
+ cursor->next = root->slots[item];
+ cursor->isOnPage = FALSE;
+ cursor->entryOffsetInPage = 0;
+ cursor->offsetInEntry = 0;
+ cursor->payload = 0;
+ traverseFromMapCursor(trie, cursor, bytes, capacity - 1, length + 1, stop, ctx, callback);
+ if (*stop)
+ return;
+ }
+ }
+}
+
+static void traverseFromMapCursorMappedPageWithPrefixCompression(Page *page, CompactMapCursor *cursor, UInt8* bytes, uint32_t capacity, uint32_t length, Boolean *stop, void *ctx, CFBurstTrieTraversalCallback callback)
+{
+ uint32_t pageSize = page->length - sizeof(Page);
+ uint32_t offset = cursor->entryOffsetInPage;
+ uint32_t minPrefixLength = 0;
+ if (cursor->isOnPage) {
+ PageEntryPacked *entry = (PageEntryPacked*)&page->data[offset];
+ int32_t remainingLength = entry->strlen - cursor->offsetInEntry - 1;
+ if (remainingLength >= 0 && remainingLength <= capacity) {
+ memcpy(bytes + length, entry->string + cursor->offsetInEntry + 1, remainingLength);
+ callback(ctx, bytes, length + remainingLength, entry->payload, stop);
+ if (*stop)
+ return;
+ }
+ minPrefixLength = entry->pfxLen + cursor->offsetInEntry;
+ offset += getPackedPageEntrySize(entry);
+ }
+ PageEntryPacked *previousEntry = NULL;
+ while (offset < pageSize) {
+ PageEntryPacked *entry = (PageEntryPacked*)&page->data[offset];
+ if (minPrefixLength > entry->pfxLen)
+ break;
+ else if (entry->payload && entry->strlen <= capacity) {
+ if (previousEntry)
+ length -= previousEntry->strlen + previousEntry->pfxLen - entry->pfxLen;
+ memcpy(bytes + length, entry->string, entry->strlen);
+ callback(ctx, bytes, length + entry->strlen, entry->payload, stop);
+ length += entry->strlen;
+ if (*stop)
+ return;
+ }
+ previousEntry = entry;
+ offset += getPackedPageEntrySize(entry);
+ }
+}
+
+static void traverseFromMapCursorMappedPageSortedByKey(Page *page, CompactMapCursor *cursor, UInt8* bytes, uint32_t capacity, uint32_t length, Boolean *stop, void *ctx, CFBurstTrieTraversalCallback callback)
+{
+ uint32_t pageSize = page->length - sizeof(Page);
+ uint32_t offset = cursor->entryOffsetInPage;
+ uint32_t prefixLength = 0;
+ const UInt8 *prefix = NULL;
+ if (cursor->isOnPage) {
+ PageEntry *entry = (PageEntry*)&page->data[offset];
+ int32_t remainingLength = entry->strlen - cursor->offsetInEntry - 1;
+ if (remainingLength >= 0 && remainingLength <= capacity) {
+ memcpy(bytes + length, entry->string + cursor->offsetInEntry, remainingLength);
+ callback(ctx, bytes, length + remainingLength, entry->payload, stop);
+ if (*stop)
+ return;
+ }
+ prefixLength = cursor->offsetInEntry + 1;
+ prefix = entry->string;
+ offset += getPageEntrySize(entry);
+ }
+
+ while (offset < pageSize) {
+ PageEntry *entry = (PageEntry*)&page->data[offset];
+ if (entry->strlen < prefixLength)
+ break;
+ else {
+ int cmpResult = __builtin_memcmp(entry->string, prefix, prefixLength);
+ if (cmpResult > 0)
+ break;
+ else if (entry->payload && entry->strlen <= capacity) {
+ if (entry->strlen > 0)
+ memcpy(bytes + length, entry->string + prefixLength, entry->strlen - prefixLength);
+ callback(ctx, bytes, length + entry->strlen - prefixLength, entry->payload, stop);
+ if (*stop)
+ return;
+ }
+ offset += getPageEntrySize(entry);
+ }
+ }
+}
+
+static void traverseFromMapCursorMappedPage(CFBurstTrieRef trie, CompactMapCursor *cursor, UInt8* bytes, uint32_t capacity, uint32_t length, Boolean *stop, void *ctx, CFBurstTrieTraversalCallback callback)
+{
+ Page *page = (Page *)DiskNextTrie_GetPtr(trie->mapBase, cursor->next);
+ if (trie->cflags & kCFBurstTrieSortByKey)
+ traverseFromMapCursorMappedPageSortedByKey(page, cursor, bytes, capacity, length, stop, ctx, callback);
+ else if (trie->cflags & kCFBurstTriePrefixCompression)
+ traverseFromMapCursorMappedPageWithPrefixCompression(page, cursor, bytes, capacity, length, stop, ctx, callback);
+}
+
+void traverseFromMapCursor(CFBurstTrieRef trie, CompactMapCursor *cursor, UInt8* bytes, uint32_t capacity, uint32_t length, Boolean *stop, void *ctx, CFBurstTrieTraversalCallback callback)
+{
+ switch (DiskNextTrie_GetKind(cursor->next)) {
+ case TrieKind:
+ traverseFromMapCursorMappedLevel(trie, cursor, bytes, capacity, length, stop, ctx, callback);
+ break;
+ case CompactTrieKind:
+ traverseFromMapCursorCompactMappedLevel(trie, cursor, bytes, capacity, length, stop, ctx, callback);
+ break;
+ case ListKind:
+ traverseFromMapCursorMappedPage(trie, cursor, bytes, capacity, length, stop, ctx, callback);
+ break;
+ case Nothing: {
+ TrieHeader *header = (TrieHeader*)trie->mapBase;
+ if (cursor->next == header->rootOffset) {
+ traverseFromMapCursorMappedLevel(trie, cursor, bytes, capacity, length, stop, ctx, callback);
+ }
+ break;
+ }
+ }
+}
+
+void copyMapCursor(const CompactMapCursor *source, CompactMapCursor* destination)
+{
+ destination->next = source->next;
+ destination->entryOffsetInPage = source->entryOffsetInPage;
+ destination->offsetInEntry = source->offsetInEntry;
+ destination->isOnPage = source->isOnPage;
+ destination->payload = source->payload;
+}
+
+Boolean areMapCursorsEqual(const CompactMapCursor *lhs, const CompactMapCursor *rhs)
+{
+ return lhs->entryOffsetInPage == rhs->entryOffsetInPage && lhs->isOnPage == rhs->isOnPage && lhs->next == rhs->next && lhs->offsetInEntry == rhs->offsetInEntry;
+}
+
+static Boolean getMapCursorPayloadFromPackedPageEntry(PageEntryPacked *entry, const CompactMapCursor *cursor, uint32_t *payload)
+{
+ if (payload)
+ *payload = 0;
+ if (cursor->entryOffsetInPage == 0 && cursor->offsetInEntry == 0 && entry->strlen == 0) {
+ if (payload)
+ *payload = entry->payload;
+ return TRUE;
+ } else if (cursor->offsetInEntry != entry->strlen - 1)
+ return FALSE;
+ else {
+ if (payload)
+ *payload = entry->payload;
+ return TRUE;
+ }
+}
+
+static Boolean getMapCursorPayloadFromPageEntry(PageEntry *entry, const CompactMapCursor *cursor, uint32_t *payload)
+{
+ if (payload)
+ *payload = 0;
+ if (cursor->entryOffsetInPage == 0 && cursor->offsetInEntry == 0 && entry->strlen == 0) {
+ if (payload)
+ *payload = entry->payload;
+ return TRUE;
+ } else if (cursor->offsetInEntry != entry->strlen - 1)
+ return FALSE;
+ else {
+ if (payload)
+ *payload = entry->payload;
+ return TRUE;
+ }
+}
+
+Boolean getMapCursorPayload(CFBurstTrieRef trie, const CompactMapCursor *cursor, uint32_t *payload)
+{
+ if (!cursor)
+ return FALSE;
+ if (cursor->payload) {
+ if (payload)
+ *payload = cursor->payload;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// Legacy
+
+static Boolean burstTrieMappedFind(DiskTrieLevelRef trie, char *map, const UInt8 *key, uint32_t length, uint32_t *payload, bool prefix) {
+ Boolean success = false;
+ if (length) {
+ uint32_t offset = CFSwapInt32LittleToHost((uint32_t)trie->slots[*key]);
+ if(DiskNextTrie_GetKind(offset) == TrieKind) {
+ return burstTrieMappedFind((DiskTrieLevelRef)DiskNextTrie_GetPtr(map,offset), map, key+1, length-1, payload, prefix);
+ } else if(DiskNextTrie_GetKind(offset) == CompactTrieKind) {
+ return burstTrieCompactTrieMappedFind((CompactDiskTrieLevelRef)DiskNextTrie_GetPtr(map, offset), map, key+1, length-1, payload, prefix);
+ } else {
+ if(DiskNextTrie_GetKind(offset) == ListKind) {
+ return burstTrieMappedPageFind((StringPage *)DiskNextTrie_GetPtr(map, offset), key+1, length-1, payload, prefix);
+ } else {
+ return success;
+ }
+ }
+ } else {
+ if (trie->weight) {
+ SetPayload(payload, CFSwapInt32LittleToHost(trie->payload));
+ success = true;
+ }
+ }
+ return success;
+}
+
+static Boolean burstTrieCompactTrieMappedFind(CompactDiskTrieLevelRef trie, char *map, const UInt8 *key, uint32_t length, uint32_t *payload, bool prefix) {
+ Boolean success = false;
+ if (length) {
+ uint32_t mykey = *key;
+ uint32_t slot = mykey / 64;
+ uint32_t bit = mykey % 64;
+ uint32_t item = 0;
+ uint64_t bword = CFSwapInt64LittleToHost(trie->bitmap[slot]);
+ if (bword & (1ull << bit)) {
+ /* Count all the set bits up to this bit */
+ for (int i=0; i < slot; i++) {
+ item += __builtin_popcountll(trie->bitmap[i]);
+ }
+ item += __builtin_popcountll(bword & ((1ull << bit)-1));
+ uint32_t offset = CFSwapInt32LittleToHost((uint32_t)trie->slots[item]);
+ if(DiskNextTrie_GetKind(offset) == TrieKind) {
+ return burstTrieMappedFind((DiskTrieLevelRef)DiskNextTrie_GetPtr(map, offset), map, key+1, length-1, payload, prefix);
+ } else if(DiskNextTrie_GetKind(offset) == CompactTrieKind) {
+ return burstTrieCompactTrieMappedFind((CompactDiskTrieLevelRef)DiskNextTrie_GetPtr(map, offset), map, key+1, length-1, payload, prefix);
+ }
+ else {
+ if(DiskNextTrie_GetKind(offset) == ListKind) {
+ return burstTrieMappedPageFind((StringPage *)DiskNextTrie_GetPtr(map, offset), key+1, length-1, payload, prefix);
+ } else {
+ return success;
+ }
+ }
+ }
+ } else {
+ if (trie->weight) {
+ SetPayload(payload, CFSwapInt32LittleToHost(trie->payload));
+ success = true;
+ }
+ }
+ return success;
+}
+
+static Boolean burstTrieMappedPageFind(StringPage *page, const UInt8 *key, uint32_t length, uint32_t *payload, bool prefix) {
+ Boolean success = false;
+ uint32_t end = CFSwapInt32LittleToHost(page->length);
+ uint32_t cur = 0;
+ if (prefix) {
+ uint8_t pfx[256];
+ while (cur < end) {
+ StringPageEntryPacked *entry = (StringPageEntryPacked *)&page->data[cur];
+ uint16_t strlen = entry->pfxLen+CFSwapInt16LittleToHost(entry->strlen);
+ if (strlen == length && __builtin_memcmp(pfx, key, entry->pfxLen) == 0 && __builtin_memcmp(entry->string, key+entry->pfxLen, length-entry->pfxLen) == 0) {
+ SetPayload(payload, CFSwapInt32LittleToHost(entry->payload));
+ success = true;
+ return success;
+ } else {
+ memcpy(pfx+entry->pfxLen, entry->string, MIN(255-entry->pfxLen, length-entry->pfxLen));
+ cur += sizeof(*entry) + strlen - entry->pfxLen;
+ }
+ }
+ } else {
+ while (cur < end) {
+ StringPageEntry *entry = (StringPageEntry *)&page->data[cur];
+ uint16_t strlen = CFSwapInt16LittleToHost(entry->strlen);
+ if (strlen == length && __builtin_memcmp(entry->string, key, length) == 0) {
+ SetPayload(payload, CFSwapInt32LittleToHost(entry->payload));
+ success = true;
+ return success;
+ } else {
+ cur += sizeof(*entry) + strlen;
+ }
+ }
+
+ }
+ return success;
+}
+
+
+#if 0
+#pragma mark -
+#pragma mark Serialization
+#endif
+
+static bool serializeCFBurstTrieLevels(CFBurstTrieRef trie, TrieLevelRef root, uint32_t *offset, off_t start_offset, bool dispose, bool isroot, int fd)
+{
+ bool dense = true;
+ int count = 0;
+
+ for (int i=0; i < CHARACTER_SET_SIZE; i++) if (root->slots[i]) count++;
+
+ uint32_t this_offset = *offset;
+
+ if ((trie->cflags & kCFBurstTrieBitmapCompression) && count < MAX_BITMAP_SIZE && !isroot) {
+ size_t size = sizeof(CompactMapTrieLevel) + sizeof(uint32_t) * count;
+ int offsetSlot = 0;
+
+ CompactMapTrieLevel *maptrie = (CompactMapTrieLevel *)alloca(size);
+ bzero(maptrie, size);
+ *offset += size;
+
+ for (int i=0; i < CHARACTER_SET_SIZE; i++) {
+ NextTrie next = root->slots[i];
+ if (next) {
+ uint32_t slot = i / 64;
+ uint32_t bit = i % 64;
+ maptrie->bitmap[slot] |= 1ull<<bit;
+ if (NextTrie_GetKind(next) == TrieKind) {
+ TrieLevelRef nextLevel = (TrieLevelRef)NextTrie_GetPtr(next);
+ uint32_t childOffset = *offset;
+ if (serializeCFBurstTrieLevels(trie, nextLevel, offset, start_offset, true, false, fd)) {
+ maptrie->slots[offsetSlot] = (TrieKind|childOffset);
+ } else {
+ maptrie->slots[offsetSlot] = (CompactTrieKind|childOffset);
+ }
+ } else {
+ maptrie->slots[offsetSlot] = next;
+ }
+ offsetSlot++;
+ }
+ }
+ maptrie->payload = root->payload;
+
+ int bitcount = 0;
+ for (int i=0; i < 4; i++) bitcount += __builtin_popcountll(maptrie->bitmap[i]);
+ assert(bitcount == count);
+
+ pwrite(fd, maptrie, size, this_offset+start_offset);
+ dense = false;
+ } else {
+ MapTrieLevel maptrie;
+ *offset += sizeof(maptrie);
+
+ for (int i=0; i < CHARACTER_SET_SIZE; i++) {
+ NextTrie next = root->slots[i];
+ if (NextTrie_GetKind(next) == TrieKind) {
+ TrieLevelRef nextLevel = (TrieLevelRef)NextTrie_GetPtr(next);
+ uint32_t childOffset = *offset;
+ if (serializeCFBurstTrieLevels(trie, nextLevel, offset, start_offset, true, false, fd)) {
+ maptrie.slots[i] = (TrieKind|childOffset);
+ } else {
+ maptrie.slots[i] = (CompactTrieKind|childOffset);
+ }
+ } else {
+ maptrie.slots[i] = next;
+ }
+ }
+ maptrie.payload = root->payload;
+ pwrite(fd, &maptrie, sizeof(maptrie), this_offset+start_offset);
+ }
+
+ if (dispose) free(root);
+ return dense;
+}
+
+static void serializeCFBurstTrieList(CFBurstTrieRef trie, ListNodeRef listNode, int fd)
+{
+ uint32_t listCount;
+ size_t size = trie->containerSize;
+
+ // ** Temp list of nodes to sort
+ ListNodeRef *nodes = (ListNodeRef *)malloc(sizeof(ListNodeRef) * size);
+ for (listCount = 0; listNode; listCount++) {
+ if (listCount >= size) {
+ size *= 2;
+ nodes = (ListNodeRef *)realloc(nodes, sizeof(ListNodeRef) * size);
+ }
+ nodes[listCount] = listNode;
+ listNode = listNode->next;
+ }
+
+ char _buffer[MAX_BUFFER_SIZE];
+ char bufferSize = (sizeof(Page) + size * (sizeof(PageEntryPacked) + MAX_STRING_SIZE));
+ char *buffer = bufferSize < MAX_BUFFER_SIZE ? _buffer : (char *) malloc(bufferSize);
+
+ Page *page = (Page *)buffer;
+ uint32_t current = 0;
+
+ if (trie->cflags & kCFBurstTriePrefixCompression) {
+ qsort(nodes, listCount, sizeof(ListNodeRef), nodeStringCompare);
+
+ ListNodeRef last = 0;
+ for (int i=0; i < listCount; i++) {
+ listNode = nodes[i];
+ uint8_t pfxLen = 0;
+ if (last) {
+ for ( ;
+ pfxLen < CHARACTER_SET_SIZE-1 &&
+ pfxLen < listNode->length &&
+ pfxLen < last->length &&
+ listNode->string[pfxLen] == last->string[pfxLen];
+ pfxLen++);
+ }
+
+ PageEntryPacked *entry = (PageEntryPacked *)(&page->data[current]);
+ entry->strlen = listNode->length - pfxLen;
+ entry->payload = listNode->payload;
+ entry->pfxLen = pfxLen;
+ memcpy(entry->string, listNode->string+pfxLen, listNode->length-pfxLen);
+ current += listNode->length - pfxLen + sizeof(PageEntryPacked);
+ last = listNode;
+ }
+ } else {
+ if (trie->cflags & kCFBurstTrieSortByKey)
+ qsort(nodes, listCount, sizeof(ListNodeRef), nodeStringCompare);
+ else
+ qsort(nodes, listCount, sizeof(ListNodeRef), nodeWeightCompare);
+
+ for (int i=0; i < listCount; i++) {
+ listNode = nodes[i];
+ PageEntry *entry = (PageEntry *)(&page->data[current]);
+ entry->strlen = listNode->length;
+ entry->payload = listNode->payload;
+ memcpy(entry->string, listNode->string, listNode->length);
+ current += listNode->length + sizeof(PageEntry);
+ }
+ }
+
+ size_t len = (sizeof(Page) + current + 3) & ~3;
+ page->length = current;
+ write(fd, page, len);
+
+ free(nodes);
+ if (buffer != _buffer) free(buffer);
+}
+
+static void serializeCFBurstTrieLists(CFBurstTrieRef trie, TrieLevelRef root, off_t start_offset, int fd)
+{
+ for (int i=0; i < CHARACTER_SET_SIZE; i++) {
+ NextTrie next = root->slots[i];
+ uint32_t offset;
+ if (NextTrie_GetKind(next) == TrieKind) {
+ TrieLevelRef nextLevel = (TrieLevelRef)NextTrie_GetPtr(next);
+ serializeCFBurstTrieLists(trie, nextLevel, start_offset, fd);
+ } else {
+ if (NextTrie_GetKind(next) == ListKind) {
+ ListNodeRef listNode = (ListNodeRef)NextTrie_GetPtr(next);
+ offset = lseek(fd, 0, SEEK_CUR) - start_offset;
+ serializeCFBurstTrieList(trie, listNode, fd);
+ finalizeCFBurstTrieList(listNode);
+ //assert((offset & 3)==0);
+ root->slots[i] = (offset|ListKind);
+ }
+ }
+ }
+}
+
+static size_t serializeCFBurstTrie(CFBurstTrieRef trie, size_t start_offset, int fd)
+{
+ TrieHeader header;
+ header.signature = 0x0ddba11;
+ header.rootOffset = 0;
+ header.count = trie->count;
+ header.size = 0;
+ header.flags = trie->cflags;
+ header.reserved[0] = 0;
+
+ uint32_t offset;
+ lseek(fd, start_offset, SEEK_SET);
+
+ size_t header_size = sizeof(header);
+ write(fd, &header, header_size);
+
+ serializeCFBurstTrieLists(trie, &trie->root, start_offset, fd);
+
+ offset = lseek(fd, 0, SEEK_CUR) - start_offset;
+ size_t off = offsetof(TrieHeader, rootOffset);
+ size_t offsize = sizeof(offset);
+ pwrite(fd, &offset, offsize, off+start_offset);
+
+ serializeCFBurstTrieLevels(trie, &trie->root, &offset, start_offset, false, true, fd);
+
+ size_t off2 = offsetof(TrieHeader, size);
+ offsize = sizeof(offset);
+ pwrite(fd, &offset, offsize, off2+start_offset);
+
+ offset = lseek(fd, 0, SEEK_END);
+ return (size_t)(offset-start_offset);
+}
+
+#if 0
+#pragma mark -
+#pragma mark Release
+#endif
+
+static void destroyCFBurstTrie(CFBurstTrieRef trie) {
+ if (trie->mapBase) {
+#if DEPLOYMENT_TARGET_WINDOWS
+ UnmapViewOfFile(trie->mapBase);
+ CloseHandle(trie->mapHandle);
+ CloseHandle(trie->mappedFileHandle);
+#else
+ munmap(trie->mapBase, trie->mapSize);
+#endif
+ } else {
+ finalizeCFBurstTrie(&trie->root);
+ }
+ free(trie);
+ return;
+}
+
+static void finalizeCFBurstTrie(TrieLevelRef trie) {
+ for (int i=0; i < CHARACTER_SET_SIZE; i++) {
+ if (NextTrie_GetKind(trie->slots[i]) == TrieKind) {
+ finalizeCFBurstTrie((TrieLevelRef)NextTrie_GetPtr(trie->slots[i]));
+ free((void *)NextTrie_GetPtr(trie->slots[i]));
+ } else if (NextTrie_GetKind(trie->slots[i]) == ListKind) {
+ finalizeCFBurstTrieList((ListNodeRef)NextTrie_GetPtr(trie->slots[i]));
+ }
+ }
+}
+
+static void finalizeCFBurstTrieList(ListNodeRef node) {
+ do {
+ ListNodeRef next = node->next;
+ free(node);
+ node = next;
+ } while(node);
+}
+
+#if 0
+#pragma mark -
+#pragma mark Helpers
+#endif
+
+static int nodeWeightCompare(const void *a, const void *b) {
+ ListNodeRef nodeA = *(ListNodeRef *)a;
+ ListNodeRef nodeB = *(ListNodeRef *)b;
+ return (nodeB->weight - nodeA->weight);
+}
+
+static int nodeStringCompare(const void *a, const void *b) {
+ ListNodeRef nodeA = *(ListNodeRef *)a;
+ ListNodeRef nodeB = *(ListNodeRef *)b;
+ int result = memcmp((char *)nodeA->string, (char *)nodeB->string, MIN(nodeA->length, nodeB->length));
+ if (result == 0) result = nodeA->length-nodeB->length;
+ return result;
+}
+
+bool containsKey(void *context, const uint8_t *key, uint32_t payload, bool exact)
+{
+ uint32_t *ctx = (uint32_t *)context;
+ if (exact) *ctx = payload;
+ return exact;
+}
+
+static CFIndex burstTrieConvertCharactersToUTF8(UniChar *chars, CFIndex numChars, UInt8 *buffer) {
+ uint32_t i, j;
+ for (i = j = 0; i < numChars; i++) {
+ UniChar c = chars[i];
+ if (CFStringIsSurrogateHighCharacter(c) && i + 1 < numChars && CFStringIsSurrogateLowCharacter(chars[i + 1])) {
+ UTF32Char lc = CFStringGetLongCharacterForSurrogatePair(c, chars[i + 1]);
+ buffer[j++] = 0xf0 + (lc >> 18);
+ buffer[j++] = 0x80 + ((lc & 0x3ffff) >> 12);
+ buffer[j++] = 0x80 + ((lc & 0xfff) >> 6);
+ buffer[j++] = 0x80 + (lc & 0x3f);
+ i++;
+ } else {
+ if (c < 0x80) {
+ buffer[j++] = c;
+ } else if (c < 0x800) {
+ buffer[j++] = 0xc0 + (c >> 6);
+ buffer[j++] = 0x80 + (c & 0x3f);
+ } else {
+ buffer[j++] = 0xe0 + (c >> 12);
+ buffer[j++] = 0x80 + ((c & 0xfff) >> 6);
+ buffer[j++] = 0x80 + (c & 0x3f);
+ }
+ }
+ }
+ buffer[j] = 0;
+ return j;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2012 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@
+ */
+
+/* CFBurstTrie.h
+ Copyright (c) 2008-2012, Apple Inc. All rights reserved.
+*/
+
+#if !defined(__COREFOUNDATION_CFBURSTTRIE__)
+#define __COREFOUNDATION_CFBURSTTRIE__ 1
+
+#include <CoreFoundation/CFString.h>
+#include <CoreFoundation/CFDictionary.h>
+
+CF_EXTERN_C_BEGIN
+
+typedef struct _CFBurstTrie *CFBurstTrieRef;
+typedef struct _CFBurstTrieCursor *CFBurstTrieCursorRef;
+
+typedef CF_OPTIONS(CFOptionFlags, CFBurstTrieOpts) {
+ /*!
+ BurstTrie Options
+ Use one or more of these options with CFBurstTrieCreate to tailor optimizations to the data
+ structure for a specific kind of application. Default is no read-write, no compression.
+ */
+
+ /* kCFBurstTrieReadOnly
+ When specified, the dictionary file will be serialized in an optimized format so as to be
+ memory-mapped on the next read. Once a trie is serialized as read-only, insertions can no
+ longer occur.
+ */
+ kCFBurstTrieReadOnly = 1<<1,
+
+ /* kCFBurstTrieBitmapCompression
+ This option can only be used with a read-only trie, and can be used to reduce on disk file size.
+ */
+ kCFBurstTrieBitmapCompression = 1<<2,
+
+ /*
+ kCFBurstTriePrefixCompression
+ This option can only be used with a read-only trie, and can be used to reduce on-disk file size.
+ It is important to note that any optimizations based on word frequency will be lost; recommended
+ for applications that often search for infrequent or uncommon words. This also allow you to use
+ cursor interface.
+ */
+ kCFBurstTriePrefixCompression = 1<<3,
+
+ /*
+ kCFBurstTriePrefixCompression
+ By default, keys at list level are sorted by weight. Use this option to sort them by key value.
+ This allow you to use cursor interface.
+ */
+ kCFBurstTrieSortByKey = 1 << 4
+};
+
+// Value for this option should be a CFNumber which contains an int.
+#define kCFBurstTrieCreationOptionNameContainerSize CFSTR("ContainerSize")
+
+typedef void (*CFBurstTrieTraversalCallback)(void* context, const UInt8* key, uint32_t keyLength, uint32_t payload, Boolean *stop);
+
+CF_EXPORT
+CFBurstTrieRef CFBurstTrieCreate() CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+CFBurstTrieRef CFBurstTrieCreateWithOptions(CFDictionaryRef options) CF_AVAILABLE(10_8, 6_0);
+
+CF_EXPORT
+CFBurstTrieRef CFBurstTrieCreateFromFile(CFStringRef path) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+CFBurstTrieRef CFBurstTrieCreateFromMapBytes(char *mapBase) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+Boolean CFBurstTrieInsert(CFBurstTrieRef trie, CFStringRef term, CFRange termRange, CFIndex payload) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+Boolean CFBurstTrieAdd(CFBurstTrieRef trie, CFStringRef term, CFRange termRange, uint32_t payload) CF_AVAILABLE(10_7, 5_0);
+
+
+CF_EXPORT
+Boolean CFBurstTrieInsertCharacters(CFBurstTrieRef trie, UniChar *chars, CFIndex numChars, CFIndex payload) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+Boolean CFBurstTrieAddCharacters(CFBurstTrieRef trie, UniChar *chars, CFIndex numChars, uint32_t payload) CF_AVAILABLE(10_7, 5_0);
+
+
+CF_EXPORT
+Boolean CFBurstTrieInsertUTF8String(CFBurstTrieRef trie, UInt8 *chars, CFIndex numChars, CFIndex payload) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+Boolean CFBurstTrieAddUTF8String(CFBurstTrieRef trie, UInt8 *chars, CFIndex numChars, uint32_t payload) CF_AVAILABLE(10_7, 5_0);
+
+
+CF_EXPORT
+Boolean CFBurstTrieInsertWithWeight(CFBurstTrieRef trie, CFStringRef term, CFRange termRange, CFIndex weight, CFIndex payload) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+Boolean CFBurstTrieAddWithWeight(CFBurstTrieRef trie, CFStringRef term, CFRange termRange, uint32_t weight, uint32_t payload) CF_AVAILABLE(10_7, 5_0);
+
+
+CF_EXPORT
+Boolean CFBurstTrieInsertCharactersWithWeight(CFBurstTrieRef trie, UniChar *chars, CFIndex numChars, CFIndex weight, CFIndex payload) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+Boolean CFBurstTrieAddCharactersWithWeight(CFBurstTrieRef trie, UniChar *chars, CFIndex numChars, uint32_t weight, uint32_t payload) CF_AVAILABLE(10_7, 5_0);
+
+
+CF_EXPORT
+Boolean CFBurstTrieInsertUTF8StringWithWeight(CFBurstTrieRef trie, UInt8 *chars, CFIndex numChars, CFIndex weight, CFIndex payload) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+Boolean CFBurstTrieAddUTF8StringWithWeight(CFBurstTrieRef trie, UInt8 *chars, CFIndex numChars, uint32_t weight, uint32_t payload) CF_AVAILABLE(10_7, 5_0);
+
+
+CF_EXPORT
+Boolean CFBurstTrieFind(CFBurstTrieRef trie, CFStringRef term, CFRange termRange, CFIndex *payload) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+Boolean CFBurstTrieContains(CFBurstTrieRef trie, CFStringRef term, CFRange termRange, uint32_t *payload) CF_AVAILABLE(10_7, 5_0);
+
+
+CF_EXPORT
+Boolean CFBurstTrieFindCharacters(CFBurstTrieRef trie, UniChar *chars, CFIndex numChars, CFIndex *payload) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+Boolean CFBurstTrieContainsCharacters(CFBurstTrieRef trie, UniChar *chars, CFIndex numChars, uint32_t *payload) CF_AVAILABLE(10_7, 5_0);
+
+
+CF_EXPORT
+Boolean CFBurstTrieFindUTF8String(CFBurstTrieRef trie, UInt8 *key, CFIndex length, CFIndex *payload) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+Boolean CFBurstTrieContainsUTF8String(CFBurstTrieRef trie, UInt8 *key, CFIndex length, uint32_t *payload) CF_AVAILABLE(10_7, 5_0);
+
+
+CF_EXPORT
+Boolean CFBurstTrieSerialize(CFBurstTrieRef trie, CFStringRef path, CFBurstTrieOpts opts) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+Boolean CFBurstTrieSerializeWithFileDescriptor(CFBurstTrieRef trie, int fd, CFBurstTrieOpts opts) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+void CFBurstTrieTraverse(CFBurstTrieRef trie, void *ctx, void (*callback)(void*, const UInt8*, uint32_t, uint32_t)) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+CFIndex CFBurstTrieGetCount(CFBurstTrieRef trie) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+CFBurstTrieRef CFBurstTrieRetain(CFBurstTrieRef trie) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+void CFBurstTrieRelease(CFBurstTrieRef trie) CF_AVAILABLE(10_7, 4_2);
+
+CF_EXPORT
+CFBurstTrieCursorRef CFBurstTrieCreateCursorForBytes(CFBurstTrieRef trie, const UInt8* bytes, CFIndex length) CF_AVAILABLE(10_8, 6_0);
+
+CF_EXPORT
+CFBurstTrieCursorRef CFBurstTrieCursorCreateByCopy(CFBurstTrieCursorRef cursor) CF_AVAILABLE(10_8, 6_0);
+
+CF_EXPORT
+Boolean CFBurstTrieSetCursorForBytes(CFBurstTrieRef trie, CFBurstTrieCursorRef cursor, const UInt8* bytes, CFIndex length) CF_AVAILABLE(10_8, 6_0);
+
+CF_EXPORT
+Boolean CFBurstTrieCursorIsEqual(CFBurstTrieCursorRef lhs, CFBurstTrieCursorRef rhs) CF_AVAILABLE(10_8, 6_0);
+
+CF_EXPORT
+Boolean CFBurstTrieCursorAdvanceForBytes(CFBurstTrieCursorRef cursor, const UInt8* bytes, CFIndex length) CF_AVAILABLE(10_8, 6_0);
+
+CF_EXPORT
+Boolean CFBurstTrieCursorGetPayload(CFBurstTrieCursorRef cursor, uint32_t *payload) CF_AVAILABLE(10_8, 6_0);
+
+CF_EXPORT
+void CFBurstTrieTraverseFromCursor(CFBurstTrieCursorRef cursor, void *ctx, CFBurstTrieTraversalCallback callback) CF_AVAILABLE(10_8, 6_0);
+
+CF_EXPORT
+void CFBurstTrieCursorRelease(CFBurstTrieCursorRef cursor) CF_AVAILABLE(10_8, 6_0);
+
+__private_extern__ const CFDictionaryValueCallBacks kCFBurstTrieValueCallbacks;
+
+CF_EXTERN_C_END
+
+#endif /* __COREFOUNDATION_CFBURSTTRIE__ */
*/
/* CFByteOrder.h
- Copyright (c) 1995-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1995-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFBYTEORDER__)
*/
/* CFCalendar.c
- Copyright (c) 2004-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2004-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
}
CFStringRef CFCalendarGetIdentifier(CFCalendarRef calendar) {
- CF_OBJC_FUNCDISPATCH0(CFCalendarGetTypeID(), CFStringRef, calendar, "calendarIdentifier");
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFStringRef, calendar, calendarIdentifier);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
return calendar->_identifier;
}
CFLocaleRef CFCalendarCopyLocale(CFCalendarRef calendar) {
- CF_OBJC_FUNCDISPATCH0(CFCalendarGetTypeID(), CFLocaleRef, calendar, "_copyLocale");
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFLocaleRef, calendar, _copyLocale);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
return (CFLocaleRef)CFLocaleCreate(kCFAllocatorSystemDefault, calendar->_localeID);
}
void CFCalendarSetLocale(CFCalendarRef calendar, CFLocaleRef locale) {
- CF_OBJC_FUNCDISPATCH1(CFCalendarGetTypeID(), void, calendar, "setLocale:", locale);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), void, calendar, setLocale:locale);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
__CFGenericValidateType(locale, CFLocaleGetTypeID());
CFStringRef localeID = CFLocaleGetIdentifier(locale);
}
CFTimeZoneRef CFCalendarCopyTimeZone(CFCalendarRef calendar) {
- CF_OBJC_FUNCDISPATCH0(CFCalendarGetTypeID(), CFTimeZoneRef, calendar, "_copyTimeZone");
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFTimeZoneRef, calendar_copyTimeZone);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
return (CFTimeZoneRef)CFRetain(calendar->_tz);
}
void CFCalendarSetTimeZone(CFCalendarRef calendar, CFTimeZoneRef tz) {
- CF_OBJC_FUNCDISPATCH1(CFCalendarGetTypeID(), void, calendar, "setTimeZone:", tz);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), void, calendar, setTimeZone:tz);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
if (tz) __CFGenericValidateType(tz, CFTimeZoneGetTypeID());
if (tz != calendar->_tz) {
}
CFIndex CFCalendarGetFirstWeekday(CFCalendarRef calendar) {
- CF_OBJC_FUNCDISPATCH0(CFCalendarGetTypeID(), CFIndex, calendar, "firstWeekday");
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFIndex, calendar, firstWeekday);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
if (!calendar->_cal) __CFCalendarSetupCal(calendar);
if (calendar->_cal) {
}
void CFCalendarSetFirstWeekday(CFCalendarRef calendar, CFIndex wkdy) {
- CF_OBJC_FUNCDISPATCH1(CFCalendarGetTypeID(), void, calendar, "setFirstWeekday:", wkdy);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), void, calendar, setFirstWeekday:wkdy);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
if (!calendar->_cal) __CFCalendarSetupCal(calendar);
if (calendar->_cal) {
}
CFIndex CFCalendarGetMinimumDaysInFirstWeek(CFCalendarRef calendar) {
- CF_OBJC_FUNCDISPATCH0(CFCalendarGetTypeID(), CFIndex, calendar, "minimumDaysInFirstWeek");
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFIndex, calendar, minimumDaysInFirstWeek);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
if (!calendar->_cal) __CFCalendarSetupCal(calendar);
return calendar->_cal ? ucal_getAttribute(calendar->_cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK) : -1;
}
void CFCalendarSetMinimumDaysInFirstWeek(CFCalendarRef calendar, CFIndex mwd) {
- CF_OBJC_FUNCDISPATCH1(CFCalendarGetTypeID(), void, calendar, "setMinimumDaysInFirstWeek:", mwd);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), void, calendar, setMinimumDaysInFirstWeek:mwd);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
if (!calendar->_cal) __CFCalendarSetupCal(calendar);
if (calendar->_cal) ucal_setAttribute(calendar->_cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK, mwd);
}
CFDateRef CFCalendarCopyGregorianStartDate(CFCalendarRef calendar) {
- CF_OBJC_FUNCDISPATCH0(CFCalendarGetTypeID(), CFDateRef, calendar, "_gregorianStartDate");
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFDateRef, calendar, _gregorianStartDate);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
if (!calendar->_cal) __CFCalendarSetupCal(calendar);
UErrorCode status = U_ZERO_ERROR;
}
void CFCalendarSetGregorianStartDate(CFCalendarRef calendar, CFDateRef date) {
- CF_OBJC_FUNCDISPATCH1(CFCalendarGetTypeID(), void, calendar, "_setGregorianStartDate:", date);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), void, calendar, _setGregorianStartDate:date);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
if (date) __CFGenericValidateType(date, CFDateGetTypeID());
if (!calendar->_cal) __CFCalendarSetupCal(calendar);
}
CFRange CFCalendarGetMinimumRangeOfUnit(CFCalendarRef calendar, CFCalendarUnit unit) {
- CF_OBJC_FUNCDISPATCH1(CFCalendarGetTypeID(), CFRange, calendar, "_minimumRangeOfUnit:", unit);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFRange, calendar, _minimumRangeOfUnit:unit);
CFRange range = {kCFNotFound, kCFNotFound};
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
if (!calendar->_cal) __CFCalendarSetupCal(calendar);
}
CFRange CFCalendarGetMaximumRangeOfUnit(CFCalendarRef calendar, CFCalendarUnit unit) {
- CF_OBJC_FUNCDISPATCH1(CFCalendarGetTypeID(), CFRange, calendar, "_maximumRangeOfUnit:", unit);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFRange, calendar, _maximumRangeOfUnit:unit);
CFRange range = {kCFNotFound, kCFNotFound};
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
if (!calendar->_cal) __CFCalendarSetupCal(calendar);
static CFRange __CFCalendarGetRangeOfUnit1(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) {
CFRange range = {kCFNotFound, kCFNotFound};
if (!__validUnits(smallerUnit, biggerUnit)) return range;
- CF_OBJC_FUNCDISPATCH3(CFCalendarGetTypeID(), CFRange, calendar, "_rangeOfUnit:inUnit:forAT:", smallerUnit, biggerUnit, at);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFRange, calendar, _rangeOfUnit:smallerUnit inUnit:biggerUnit forAT:at);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
if (!calendar->_cal) __CFCalendarSetupCal(calendar);
if (calendar->_cal) {
static CFRange __CFCalendarGetRangeOfUnit2(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) __attribute__((noinline));
static CFRange __CFCalendarGetRangeOfUnit2(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) {
- CF_OBJC_FUNCDISPATCH3(CFCalendarGetTypeID(), CFRange, calendar, "_rangeOfUnit:inUnit:forAT:", smallerUnit, biggerUnit, at);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFRange, calendar, _rangeOfUnit:smallerUnit inUnit:biggerUnit forAT:at);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
CFRange range = {kCFNotFound, kCFNotFound};
if (!calendar->_cal) __CFCalendarSetupCal(calendar);
}
CFRange CFCalendarGetRangeOfUnit(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) {
- if (_CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard)) {
return __CFCalendarGetRangeOfUnit2(calendar, smallerUnit, biggerUnit, at);
- } else {
- return __CFCalendarGetRangeOfUnit1(calendar, smallerUnit, biggerUnit, at);
- }
}
CFIndex CFCalendarGetOrdinalityOfUnit(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) {
CFIndex result = kCFNotFound;
if (!__validUnits(smallerUnit, biggerUnit)) return result;
- CF_OBJC_FUNCDISPATCH3(CFCalendarGetTypeID(), CFIndex, calendar, "_ordinalityOfUnit:inUnit:forAT:", smallerUnit, biggerUnit, at);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFIndex, calendar, _ordinalityOfUnit:smallerUnit inUnit:biggerUnit forAT:at);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
if (!calendar->_cal) __CFCalendarSetupCal(calendar);
if (calendar->_cal) {
Boolean CFCalendarComposeAbsoluteTime(CFCalendarRef calendar, /* out */ CFAbsoluteTime *atp, const char *componentDesc, ...) {
va_list args;
va_start(args, componentDesc);
- CF_OBJC_FUNCDISPATCH3(CFCalendarGetTypeID(), Boolean, calendar, "_composeAbsoluteTime:::", atp, componentDesc, args);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), Boolean, calendar, _composeAbsoluteTime:atp :componentDesc :args);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
int idx, cnt = strlen((char *)componentDesc);
STACK_BUFFER_DECL(int, vector, cnt);
Boolean CFCalendarDecomposeAbsoluteTime(CFCalendarRef calendar, CFAbsoluteTime at, const char *componentDesc, ...) {
va_list args;
va_start(args, componentDesc);
- CF_OBJC_FUNCDISPATCH3(CFCalendarGetTypeID(), Boolean, calendar, "_decomposeAbsoluteTime:::", at, componentDesc, args);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), Boolean, calendar, _decomposeAbsoluteTime:at :componentDesc :args);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
int idx, cnt = strlen((char *)componentDesc);
STACK_BUFFER_DECL(int *, vector, cnt);
Boolean CFCalendarAddComponents(CFCalendarRef calendar, /* inout */ CFAbsoluteTime *atp, CFOptionFlags options, const char *componentDesc, ...) {
va_list args;
va_start(args, componentDesc);
- CF_OBJC_FUNCDISPATCH4(CFCalendarGetTypeID(), Boolean, calendar, "_addComponents::::", atp, options, componentDesc, args);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), Boolean, calendar, _addComponents:atp :options :componentDesc :args);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
int idx, cnt = strlen((char *)componentDesc);
STACK_BUFFER_DECL(int, vector, cnt);
Boolean CFCalendarGetComponentDifference(CFCalendarRef calendar, CFAbsoluteTime startingAT, CFAbsoluteTime resultAT, CFOptionFlags options, const char *componentDesc, ...) {
va_list args;
va_start(args, componentDesc);
- CF_OBJC_FUNCDISPATCH5(CFCalendarGetTypeID(), Boolean, calendar, "_diffComponents:::::", startingAT, resultAT, options, componentDesc, args);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), Boolean, calendar, _diffComponents:startingAT :resultAT :options :componentDesc :args);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
int idx, cnt = strlen((char *)componentDesc);
STACK_BUFFER_DECL(int *, vector, cnt);
}
Boolean CFCalendarGetTimeRangeOfUnit(CFCalendarRef calendar, CFCalendarUnit unit, CFAbsoluteTime at, CFAbsoluteTime *startp, CFTimeInterval *tip) {
- CF_OBJC_FUNCDISPATCH4(CFCalendarGetTypeID(), Boolean, calendar, "_rangeOfUnit:startTime:interval:forAT:", unit, startp, tip, at);
+ CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), Boolean, calendar, _rangeOfUnit:unit startTime:startp interval:tip forAT:at);
__CFGenericValidateType(calendar, CFCalendarGetTypeID());
if (kCFCalendarUnitWeekdayOrdinal == unit) return false;
if (kCFCalendarUnitWeekday == unit) unit = kCFCalendarUnitDay;
*/
/* CFCalendar.h
- Copyright (c) 2004-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2004-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFCALENDAR__)
#include <CoreFoundation/CFDate.h>
#include <CoreFoundation/CFTimeZone.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
typedef struct __CFCalendar * CFCalendarRef;
void CFCalendarSetMinimumDaysInFirstWeek(CFCalendarRef calendar, CFIndex mwd);
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFCalendarUnit) {
kCFCalendarUnitEra = (1UL << 1),
kCFCalendarUnitYear = (1UL << 2),
kCFCalendarUnitMonth = (1UL << 3),
kCFCalendarUnitWeek = (1UL << 8) /* CF_DEPRECATED(10_4, 10_7, 2_0, 5_0) */,
kCFCalendarUnitWeekday = (1UL << 9),
kCFCalendarUnitWeekdayOrdinal = (1UL << 10),
-#if MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED || __IPHONE_4_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED
- kCFCalendarUnitQuarter = (1UL << 11),
-#endif
-#if MAC_OS_X_VERSION_10_7 <= MAC_OS_X_VERSION_MAX_ALLOWED || __IPHONE_5_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED
- kCFCalendarUnitWeekOfMonth = (1UL << 12),
- kCFCalendarUnitWeekOfYear = (1UL << 13),
- kCFCalendarUnitYearForWeekOfYear = (1UL << 14),
-#endif
+ kCFCalendarUnitQuarter CF_ENUM_AVAILABLE(10_6, 4_0) = (1UL << 11),
+ kCFCalendarUnitWeekOfMonth CF_ENUM_AVAILABLE(10_7, 5_0) = (1UL << 12),
+ kCFCalendarUnitWeekOfYear CF_ENUM_AVAILABLE(10_7, 5_0) = (1UL << 13),
+ kCFCalendarUnitYearForWeekOfYear CF_ENUM_AVAILABLE(10_7, 5_0) = (1UL << 14),
};
-typedef CFOptionFlags CFCalendarUnit;
CF_EXPORT
CFRange CFCalendarGetMinimumRangeOfUnit(CFCalendarRef calendar, CFCalendarUnit unit);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFCALENDAR__ */
*/
/* CFCharacterSet.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Aki Inoue
*/
CFCharacterSetRef CFCharacterSetCreateInvertedSet(CFAllocatorRef alloc, CFCharacterSetRef theSet) {
CFMutableCharacterSetRef cset;
- CF_OBJC_FUNCDISPATCH0(__kCFCharacterSetTypeID, CFCharacterSetRef , theSet, "invertedSet");
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, CFCharacterSetRef , (NSCharacterSet *)theSet, invertedSet);
cset = CFCharacterSetCreateMutableCopy(alloc, theSet);
CFCharacterSetInvert(cset);
static CFMutableCharacterSetRef __CFCharacterSetCreateCopy(CFAllocatorRef alloc, CFCharacterSetRef theSet, bool isMutable) {
CFMutableCharacterSetRef cset;
- CF_OBJC_FUNCDISPATCH0(__kCFCharacterSetTypeID, CFMutableCharacterSetRef , theSet, "mutableCopy");
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, CFMutableCharacterSetRef , (NSCharacterSet *)theSet, mutableCopy);
__CFGenericValidateType(theSet, __kCFCharacterSetTypeID);
Boolean isInverted;
Boolean result = false;
- CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, Boolean, theSet, "longCharacterIsMember:", theChar);
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, Boolean, (NSCharacterSet *)theSet, longCharacterIsMember:(UTF32Char)theChar);
__CFGenericValidateType(theSet, __kCFCharacterSetTypeID);
Boolean isInverted;
Boolean result = false;
- CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, Boolean, theSet, "longCharacterIsMember:", theChar);
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, Boolean, (NSCharacterSet *)theSet, longCharacterIsMember:(UTF32Char)theChar);
__CFGenericValidateType(theSet, __kCFCharacterSetTypeID);
static inline CFCharacterSetRef __CFCharacterSetGetExpandedSetForNSCharacterSet(const void *characterSet) {
- CF_OBJC_FUNCDISPATCH0(__kCFCharacterSetTypeID, CFCharacterSetRef , characterSet, "_expandedCFCharacterSet");
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, CFCharacterSetRef , (NSCharacterSet *)characterSet, _expandedCFCharacterSet);
return NULL;
}
Boolean CFCharacterSetHasMemberInPlane(CFCharacterSetRef theSet, CFIndex thePlane) {
Boolean isInverted = __CFCSetIsInverted(theSet);
- CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, Boolean, theSet, "hasMemberInPlane:", thePlane);
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, Boolean, (NSCharacterSet *)theSet, hasMemberInPlane:(uint8_t)thePlane);
if (__CFCSetIsEmpty(theSet)) {
return (isInverted ? TRUE : FALSE);
int length;
bool isAnnexInverted;
- CF_OBJC_FUNCDISPATCH0(__kCFCharacterSetTypeID, CFDataRef , theSet, "_retainedBitmapRepresentation");
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, CFDataRef , (NSCharacterSet *)theSet, _retainedBitmapRepresentation);
__CFGenericValidateType(theSet, __kCFCharacterSetTypeID);
/*** MutableCharacterSet functions ***/
void CFCharacterSetAddCharactersInRange(CFMutableCharacterSetRef theSet, CFRange theRange) {
- CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "addCharactersInRange:", theRange);
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, void, (NSMutableCharacterSet *)theSet, addCharactersInRange:NSMakeRange(theRange.location, theRange.length));
__CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__);
__CFCSetValidateRange(theRange, __PRETTY_FUNCTION__);
CFIndex length = __CFCSetRangeLength(theSet);
if (firstChar == theRange.location) {
- __CFCSetPutRangeLength(theSet, __CFMin(length, theRange.length));
+ __CFCSetPutRangeLength(theSet, __CFMax(length, theRange.length));
__CFCSetPutHasHashValue(theSet, false);
return;
} else if (firstChar < theRange.location && theRange.location <= firstChar + length) {
}
void CFCharacterSetRemoveCharactersInRange(CFMutableCharacterSetRef theSet, CFRange theRange) {
- CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "removeCharactersInRange:", theRange);
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, void, (NSMutableCharacterSet *)theSet, removeCharactersInRange:NSMakeRange(theRange.location, theRange.length));
__CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__);
__CFCSetValidateRange(theRange, __PRETTY_FUNCTION__);
CFIndex length;
BOOL hasSurrogate = NO;
- CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "addCharactersInString:", theString);
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, void, (NSMutableCharacterSet *)theSet, addCharactersInString:(NSString *)theString);
__CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__);
CFIndex length;
BOOL hasSurrogate = NO;
- CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "removeCharactersInString:", theString);
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, void, (NSMutableCharacterSet *)theSet, removeCharactersInString:(NSString *)theString);
__CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__);
void CFCharacterSetUnion(CFMutableCharacterSetRef theSet, CFCharacterSetRef theOtherSet) {
CFCharacterSetRef expandedSet = NULL;
- CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "formUnionWithCharacterSet:", theOtherSet);
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, void, (NSMutableCharacterSet *)theSet, formUnionWithCharacterSet:(NSCharacterSet *)theOtherSet);
__CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__);
void CFCharacterSetIntersect(CFMutableCharacterSetRef theSet, CFCharacterSetRef theOtherSet) {
CFCharacterSetRef expandedSet = NULL;
- CF_OBJC_FUNCDISPATCH1(__kCFCharacterSetTypeID, void, theSet, "formIntersectionWithCharacterSet:", theOtherSet);
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, void, (NSMutableCharacterSet *)theSet, formIntersectionWithCharacterSet:(NSCharacterSet *)theOtherSet);
__CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__);
void CFCharacterSetInvert(CFMutableCharacterSetRef theSet) {
- CF_OBJC_FUNCDISPATCH0(__kCFCharacterSetTypeID, void, theSet, "invert");
+ CF_OBJC_FUNCDISPATCHV(__kCFCharacterSetTypeID, void, (NSMutableCharacterSet *)theSet, invert);
__CFCSetValidateTypeAndMutability(theSet, __PRETTY_FUNCTION__);
*/
/* CFCharacterSet.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
/*!
#include <CoreFoundation/CFBase.h>
#include <CoreFoundation/CFData.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
/*!
Type of the predefined CFCharacterSet selector values.
*/
-enum {
+typedef CF_ENUM(CFIndex, CFCharacterSetPredefinedSet) {
kCFCharacterSetControl = 1, /* Control character set (Unicode General Category Cc and Cf) */
kCFCharacterSetWhitespace, /* Whitespace character set (Unicode General Category Zs and U0009 CHARACTER TABULATION) */
kCFCharacterSetWhitespaceAndNewline, /* Whitespace and Newline character set (Unicode General Category Z*, U000A ~ U000D, and U0085) */
kCFCharacterSetPunctuation, /* Punctuation character set (Unicode General Category P*) */
kCFCharacterSetCapitalizedLetter = 13, /* Titlecase character set (Unicode General Category Lt) */
kCFCharacterSetSymbol = 14, /* Symbol character set (Unicode General Category S*) */
-#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
- kCFCharacterSetNewline = 15, /* Newline character set (U000A ~ U000D, U0085, U2028, and U2029) */
-#endif
+ kCFCharacterSetNewline CF_ENUM_AVAILABLE(10_5, 2_0) = 15, /* Newline character set (U000A ~ U000D, U0085, U2028, and U2029) */
kCFCharacterSetIllegal = 12/* Illegal character set */
};
-typedef CFIndex CFCharacterSetPredefinedSet;
/*!
@function CFCharacterSetGetTypeID
void CFCharacterSetInvert(CFMutableCharacterSetRef theSet);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFCHARACTERSET__ */
*/
/* CFCharacterSetPriv.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFCHARACTERSETPRIV__)
@result The UTF-32 value for the surrogate pair.
*/
CF_INLINE UTF32Char CFCharacterSetGetLongCharacterForSurrogatePair(UniChar surrogateHigh, UniChar surrogateLow) {
- return ((surrogateHigh - 0xD800UL) << 10) + (surrogateLow - 0xDC00UL) + 0x0010000UL;
+ return (UTF32Char)(((surrogateHigh - 0xD800UL) << 10) + (surrogateLow - 0xDC00UL) + 0x0010000UL);
}
/* Check to see if the character represented by the surrogate pair surrogateHigh & surrogateLow is in the chraracter set */
/* Keyed-coding support
*/
-enum {
+typedef CF_ENUM(CFIndex, CFCharacterSetKeyedCodingType) {
kCFCharacterSetKeyedCodingTypeBitmap = 1,
kCFCharacterSetKeyedCodingTypeBuiltin = 2,
kCFCharacterSetKeyedCodingTypeRange = 3,
kCFCharacterSetKeyedCodingTypeString = 4,
kCFCharacterSetKeyedCodingTypeBuiltinAndBitmap = 5
};
-typedef CFIndex CFCharacterSetKeyedCodingType;
CF_EXPORT CFCharacterSetKeyedCodingType _CFCharacterSetGetKeyedCodingType(CFCharacterSetRef cset);
CF_EXPORT CFCharacterSetPredefinedSet _CFCharacterSetGetKeyedCodingBuiltinType(CFCharacterSetRef cset);
*/
/* CFConcreteStreams.c
- Copyright (c) 2000-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2000-2012, Apple Inc. All rights reserved.
Responsibility: John Iarocci
*/
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
#include <sys/time.h>
#include <unistd.h>
-#elif DEPLOYMENT_TARGET_WINDOWS
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
CONST_STRING_DECL(kCFStreamPropertyFileCurrentOffset, "kCFStreamPropertyFileCurrentOffset");
-
+#if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
+CONST_STRING_DECL(_kCFStreamPropertyFileNativeHandle, "_kCFStreamPropertyFileNativeHandle");
+#endif
#ifdef REAL_FILE_SCHEDULING
extern void _CFFileDescriptorInduceFakeReadCallBack(CFFileDescriptorRef);
wchar_t path[CFMaxPathSize];
flags |= (_O_BINARY|_O_NOINHERIT);
if (_CFURLGetWideFileSystemRepresentation(fileStream->url, TRUE, path, CFMaxPathSize) == FALSE)
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
char path[CFMaxPathSize];
if (CFURLGetFileSystemRepresentation(fileStream->url, TRUE, (UInt8 *)path, CFMaxPathSize) == FALSE)
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
{
error->error = ENOENT;
}
do {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
fileStream->fd = open((const char *)path, flags, 0666);
#elif DEPLOYMENT_TARGET_WINDOWS
fileStream->fd = _wopen(path, flags, 0666);
if (fileStream->offset != -1) {
result = CFNumberCreate(CFGetAllocator((CFTypeRef)stream), kCFNumberSInt64Type, &(fileStream->offset));
}
- }
+#if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
+ } else if (CFEqual(propertyName, _kCFStreamPropertyFileNativeHandle)) {
+ int fd = fileStream->fd;
+ if (fd != -1) {
+ result = CFDataCreate(CFGetAllocator((CFTypeRef) stream), (const uint8_t *)&fd, sizeof(fd));
+ }
+#endif
+ }
return result;
}
*/
/* CFData.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Kevin Perry
*/
#include <CoreFoundation/CFPriv.h>
#include "CFInternal.h"
#include <string.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#include <mach/mach_init.h>
-#elif DEPLOYMENT_TARGET_WINDOWS
-#include <windows.h> // For GetSystemInfo()
-#endif
+
+
#if __LP64__
#define CFDATA_MAX_SIZE ((1ULL << 42) - 1)
#define CFDATA_MAX_SIZE ((1ULL << 31) - 1)
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
+#import <mach/mach.h>
CF_INLINE unsigned long __CFPageSize() { return vm_page_size; }
#elif DEPLOYMENT_TARGET_WINDOWS
CF_INLINE unsigned long __CFPageSize() {
return 16;
} else if (capacity < LOW_THRESHOLD) {
/* Up to 4x */
- int idx = flsl(capacity);
- return (1 << (idx + ((idx % 2 == 0) ? 0 : 1)));
+ long idx = flsl(capacity);
+ return (1L << (long)(idx + ((idx % 2 == 0) ? 0 : 1)));
} else if (capacity < HIGH_THRESHOLD) {
/* Up to 2x */
- return (1 << flsl(capacity));
+ return (1L << (long)flsl(capacity));
} else {
/* Round up to next multiple of CHUNK_SIZE */
- unsigned long newCapacity = CHUNK_SIZE * (1+(capacity >> (flsl(CHUNK_SIZE)-1)));
+ unsigned long newCapacity = CHUNK_SIZE * (1+(capacity >> ((long)flsl(CHUNK_SIZE)-1)));
return __CFMin(newCapacity, CFDATA_MAX_SIZE);
}
}
}
CFIndex CFDataGetLength(CFDataRef data) {
- CF_OBJC_FUNCDISPATCH0(__kCFDataTypeID, CFIndex, data, "length");
+ CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, CFIndex, (NSData *)data, length);
__CFGenericValidateType(data, __kCFDataTypeID);
return __CFDataLength(data);
}
const uint8_t *CFDataGetBytePtr(CFDataRef data) {
- CF_OBJC_FUNCDISPATCH0(__kCFDataTypeID, const uint8_t *, data, "bytes");
+ CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, const uint8_t *, (NSData *)data, bytes);
__CFGenericValidateType(data, __kCFDataTypeID);
// compaction: if inline, always do the computation.
return __CFDataBytesInline(data) ? (uint8_t *)__CFDataInlineBytesPtr(data) : data->_bytes;
}
uint8_t *CFDataGetMutableBytePtr(CFMutableDataRef data) {
- CF_OBJC_FUNCDISPATCH0(__kCFDataTypeID, uint8_t *, data, "mutableBytes");
+ CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, uint8_t *, (NSMutableData *)data, mutableBytes);
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
// compaction: if inline, always do the computation.
return __CFDataBytesInline(data) ? (uint8_t *)__CFDataInlineBytesPtr(data) : data->_bytes;
}
void CFDataGetBytes(CFDataRef data, CFRange range, uint8_t *buffer) {
- CF_OBJC_FUNCDISPATCH2(__kCFDataTypeID, void, data, "getBytes:range:", buffer, range);
+ CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, void, (NSData *)data, getBytes:(void *)buffer range:NSMakeRange(range.location, range.length));
__CFDataValidateRange(data, range, __PRETTY_FUNCTION__);
memmove(buffer, CFDataGetBytePtr(data) + range.location, range.length);
}
void CFDataSetLength(CFMutableDataRef data, CFIndex newLength) {
CFIndex oldLength, capacity;
Boolean isGrowable;
- CF_OBJC_FUNCDISPATCH1(__kCFDataTypeID, void, data, "setLength:", newLength);
+ CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, void, (NSMutableData *)data, setLength:(NSUInteger)newLength);
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
oldLength = __CFDataLength(data);
capacity = __CFDataCapacity(data);
}
void CFDataIncreaseLength(CFMutableDataRef data, CFIndex extraLength) {
- CF_OBJC_FUNCDISPATCH1(__kCFDataTypeID, void, data, "increaseLengthBy:", extraLength);
+ CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, void, (NSMutableData *)data, increaseLengthBy:(NSUInteger)extraLength);
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
if (extraLength < 0) HALT; // Avoid integer overflow.
CFDataSetLength(data, __CFDataLength(data) + extraLength);
}
void CFDataAppendBytes(CFMutableDataRef data, const uint8_t *bytes, CFIndex length) {
- CF_OBJC_FUNCDISPATCH2(__kCFDataTypeID, void, data, "appendBytes:length:", bytes, length);
+ CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, void, (NSMutableData *)data, appendBytes:(const void *)bytes length:(NSUInteger)length);
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
CFDataReplaceBytes(data, CFRangeMake(__CFDataLength(data), 0), bytes, length);
}
void CFDataDeleteBytes(CFMutableDataRef data, CFRange range) {
- CF_OBJC_FUNCDISPATCH3(__kCFDataTypeID, void, data, "replaceBytesInRange:withBytes:length:", range, NULL, 0);
+ CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, void, (NSMutableData *)data, replaceBytesInRange:NSMakeRange(range.location, range.length) withBytes:NULL length:0);
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
CFDataReplaceBytes(data, range, NULL, 0);
}
void CFDataReplaceBytes(CFMutableDataRef data, CFRange range, const uint8_t *newBytes, CFIndex newLength) {
- CF_OBJC_FUNCDISPATCH3(__kCFDataTypeID, void, data, "replaceBytesInRange:withBytes:length:", range, newBytes, newLength);
+ CF_OBJC_FUNCDISPATCHV(__kCFDataTypeID, void, (NSMutableData *)data, replaceBytesInRange:NSMakeRange(range.location, range.length) withBytes:(const void *)newBytes length:(NSUInteger)newLength);
__CFGenericValidateType(data, __kCFDataTypeID);
__CFDataValidateRange(data, range, __PRETTY_FUNCTION__);
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
*/
/* CFData.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFDATA__)
#include <CoreFoundation/CFBase.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
typedef const struct __CFData * CFDataRef;
CF_EXPORT
void CFDataDeleteBytes(CFMutableDataRef theData, CFRange range);
-#if MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED || __IPHONE_4_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFDataSearchFlags) {
kCFDataSearchBackwards = 1UL << 0,
kCFDataSearchAnchored = 1UL << 1
-};
-#endif
-typedef CFOptionFlags CFDataSearchFlags;
+} CF_ENUM_AVAILABLE(10_6, 4_0);
CF_EXPORT
CFRange CFDataFind(CFDataRef theData, CFDataRef dataToFind, CFRange searchRange, CFDataSearchFlags compareOptions) CF_AVAILABLE(10_6, 4_0);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFDATA__ */
*/
/* CFDate.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
#include <CoreFoundation/CFNumber.h>
#include "CFInternal.h"
#include <math.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
#include <sys/time.h>
-#elif DEPLOYMENT_TARGET_WINDOWS
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
+#define DEFINE_CFDATE_FUNCTIONS 1
/* cjk: The Julian Date for the reference date is 2451910.5,
I think, in case that's ever useful. */
-#define DEFINE_CFDATE_FUNCTIONS 1
-
#if DEFINE_CFDATE_FUNCTIONS
const CFTimeInterval kCFAbsoluteTimeIntervalSince1970 = 978307200.0L;
CFAbsoluteTime CFAbsoluteTimeGetCurrent(void) {
CFAbsoluteTime ret;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
struct timeval tv;
gettimeofday(&tv, NULL);
ret = (CFTimeInterval)tv.tv_sec - kCFAbsoluteTimeIntervalSince1970;
ret += (1.0E-6 * (CFTimeInterval)tv.tv_usec);
-#elif DEPLOYMENT_TARGET_WINDOWS
- FILETIME ft;
- GetSystemTimeAsFileTime(&ft);
- ret = _CFAbsoluteTimeFromFileTime(&ft);
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
-#endif
return ret;
}
__private_extern__ void __CFDateInitialize(void) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
struct mach_timebase_info info;
mach_timebase_info(&info);
__CFTSRRate = (1.0E9 / (double)info.numer) * (double)info.denom;
__CFTSRRate = res.tv_sec + (1000000000 * res.tv_nsec);
__CF1_TSRRate = 1.0 / __CFTSRRate;
#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
+#error Unable to initialize date
#endif
CFDateGetTypeID(); // cause side-effects
}
-#if 1
struct __CFDate {
CFRuntimeBase _base;
CFAbsoluteTime _time; /* immutable */
}
CFTimeInterval CFDateGetAbsoluteTime(CFDateRef date) {
- CF_OBJC_FUNCDISPATCH0(CFDateGetTypeID(), CFTimeInterval, date, "timeIntervalSinceReferenceDate");
+ CF_OBJC_FUNCDISPATCHV(CFDateGetTypeID(), CFTimeInterval, (NSDate *)date, timeIntervalSinceReferenceDate);
__CFGenericValidateType(date, CFDateGetTypeID());
return date->_time;
}
CFTimeInterval CFDateGetTimeIntervalSinceDate(CFDateRef date, CFDateRef otherDate) {
- CF_OBJC_FUNCDISPATCH1(CFDateGetTypeID(), CFTimeInterval, date, "timeIntervalSinceDate:", otherDate);
+ CF_OBJC_FUNCDISPATCHV(CFDateGetTypeID(), CFTimeInterval, (NSDate *)date, timeIntervalSinceDate:(NSDate *)otherDate);
__CFGenericValidateType(date, CFDateGetTypeID());
__CFGenericValidateType(otherDate, CFDateGetTypeID());
return date->_time - otherDate->_time;
}
CFComparisonResult CFDateCompare(CFDateRef date, CFDateRef otherDate, void *context) {
- CF_OBJC_FUNCDISPATCH1(CFDateGetTypeID(), CFComparisonResult, date, "compare:", otherDate);
+ CF_OBJC_FUNCDISPATCHV(CFDateGetTypeID(), CFComparisonResult, (NSDate *)date, compare:(NSDate *)otherDate);
__CFGenericValidateType(date, CFDateGetTypeID());
__CFGenericValidateType(otherDate, CFDateGetTypeID());
if (date->_time < otherDate->_time) return kCFCompareLessThan;
if (date->_time > otherDate->_time) return kCFCompareGreaterThan;
return kCFCompareEqualTo;
}
-#endif
#endif
CFAbsoluteTime CFGregorianDateGetAbsoluteTime(CFGregorianDate gdate, CFTimeZoneRef tz) {
CFAbsoluteTime at;
- CFTimeInterval offset0, offset1;
+ at = 86400.0 * __CFAbsoluteFromYMD(gdate.year - 2001, gdate.month, gdate.day);
+ at += 3600.0 * gdate.hour + 60.0 * gdate.minute + gdate.second;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (NULL != tz) {
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
}
- at = 86400.0 * __CFAbsoluteFromYMD(gdate.year - 2001, gdate.month, gdate.day);
- at += 3600.0 * gdate.hour + 60.0 * gdate.minute + gdate.second;
+ CFTimeInterval offset0, offset1;
if (NULL != tz) {
offset0 = CFTimeZoneGetSecondsFromGMT(tz, at);
offset1 = CFTimeZoneGetSecondsFromGMT(tz, at - offset0);
at -= offset1;
}
+#endif
return at;
}
int64_t absolute, year;
int8_t month, day;
CFAbsoluteTime fixedat;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (NULL != tz) {
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
}
fixedat = at + (NULL != tz ? CFTimeZoneGetSecondsFromGMT(tz, at) : 0.0);
+#else
+ fixedat = at;
+#endif
absolute = (int64_t)floor(fixedat / 86400.0);
__CFYMDFromAbsolute(absolute, &year, &month, &day);
if (INT32_MAX - 2001 < year) year = INT32_MAX - 2001;
CFAbsoluteTime candidate_at0, candidate_at1;
uint8_t monthdays;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (NULL != tz) {
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
}
-
+#endif
+
/* Most people seem to expect years, then months, then days, etc.
to be added in that order. Thus, 27 April + (4 days, 1 month)
= 31 May, and not 1 June. This is also relatively predictable.
SInt32 CFAbsoluteTimeGetDayOfWeek(CFAbsoluteTime at, CFTimeZoneRef tz) {
int64_t absolute;
CFAbsoluteTime fixedat;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (NULL != tz) {
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
}
fixedat = at + (NULL != tz ? CFTimeZoneGetSecondsFromGMT(tz, at) : 0.0);
+#else
+ fixedat = at;
+#endif
absolute = (int64_t)floor(fixedat / 86400.0);
return (absolute < 0) ? ((absolute + 1) % 7 + 7) : (absolute % 7 + 1); /* Monday = 1, etc. */
}
CFAbsoluteTime fixedat;
int64_t absolute, year;
int8_t month, day;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (NULL != tz) {
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
}
fixedat = at + (NULL != tz ? CFTimeZoneGetSecondsFromGMT(tz, at) : 0.0);
+#else
+ fixedat = at;
+#endif
absolute = (int64_t)floor(fixedat / 86400.0);
__CFYMDFromAbsolute(absolute, &year, &month, &day);
return __CFDaysBeforeMonth(month, year, isleap(year)) + day;
int64_t absolute, year;
int8_t month, day;
CFAbsoluteTime fixedat;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (NULL != tz) {
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
}
fixedat = at + (NULL != tz ? CFTimeZoneGetSecondsFromGMT(tz, at) : 0.0);
+#else
+ fixedat = at;
+#endif
absolute = (int64_t)floor(fixedat / 86400.0);
__CFYMDFromAbsolute(absolute, &year, &month, &day);
double absolute0101 = __CFAbsoluteFromYMD(year, 1, 1);
*/
/* CFDate.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFDATE__)
#include <CoreFoundation/CFBase.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
typedef double CFTimeInterval;
CF_EXPORT
CFComparisonResult CFDateCompare(CFDateRef theDate, CFDateRef otherDate, void *context);
+CF_IMPLICIT_BRIDGING_DISABLED
+
typedef const struct __CFTimeZone * CFTimeZoneRef;
typedef struct {
double seconds;
} CFGregorianUnits;
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFGregorianUnitFlags) {
kCFGregorianUnitsYears = (1UL << 0),
kCFGregorianUnitsMonths = (1UL << 1),
kCFGregorianUnitsDays = (1UL << 2),
kCFGregorianUnitsSeconds = (1UL << 5),
kCFGregorianAllUnits = 0x00FFFFFF
};
-typedef CFOptionFlags CFGregorianUnitFlags;
CF_EXPORT
Boolean CFGregorianDateIsValid(CFGregorianDate gdate, CFOptionFlags unitFlags);
*/
/* CFDateFormatter.c
- Copyright (c) 2002-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2002-2012, Apple Inc. All rights reserved.
Responsibility: David Smith
*/
#include <math.h>
#include <float.h>
+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
+ kCFDateFormatterAmbiguousYearAssumeToCurrent = 2, // default to assuming the current century or era
+ kCFDateFormatterAmbiguousYearAssumeToCenteredAroundCurrentDate = 3,
+ kCFDateFormatterAmbiguousYearAssumeToFuture = 4,
+ kCFDateFormatterAmbiguousYearAssumeToPast = 5,
+ kCFDateFormatterAmbiguousYearAssumeToLikelyFuture = 6,
+ kCFDateFormatterAmbiguousYearAssumeToLikelyPast = 7
+};
+
extern UCalendar *__CFCalendarCreateUCalendar(CFStringRef calendarID, CFStringRef localeID, CFTimeZoneRef tz);
static void __CFDateFormatterCustomize(CFDateFormatterRef formatter);
CFBooleanRef _IsLenient;
CFBooleanRef _DoesRelativeDateFormatting;
CFBooleanRef _HasCustomFormat;
- CFTimeZoneRef _TimeZone;
+ CFTimeZoneRef _TimeZone;
CFCalendarRef _Calendar;
CFStringRef _CalendarName;
CFDateRef _TwoDigitStartDate;
CFArrayRef _ShortStandaloneQuarterSymbols;
CFStringRef _AMSymbol;
CFStringRef _PMSymbol;
+ CFNumberRef _AmbiguousYearStrategy;
} _property;
};
CFReleaseIfNotNull(formatter->_property._ShortStandaloneQuarterSymbols);
CFReleaseIfNotNull(formatter->_property._AMSymbol);
CFReleaseIfNotNull(formatter->_property._PMSymbol);
+ CFReleaseIfNotNull(formatter->_property._AmbiguousYearStrategy);
}
static CFStringRef __CFDateFormatterCreateForcedString(CFDateFormatterRef formatter, CFStringRef inString);
}
Boolean wantRelative = (NULL != df->_property._DoesRelativeDateFormatting && df->_property._DoesRelativeDateFormatting == kCFBooleanTrue);
Boolean hasFormat = (NULL != df->_property._HasCustomFormat && df->_property._HasCustomFormat == kCFBooleanTrue) || goingToHaveCustomFormat;
- if (wantRelative && !hasFormat) {
+ if (wantRelative && !hasFormat && kCFDateFormatterNoStyle != df->_dateStyle) {
udstyle |= UDAT_RELATIVE;
}
}
udat_setLenient(icudf, 0);
if (kCFDateFormatterNoStyle == df->_dateStyle && kCFDateFormatterNoStyle == df->_timeStyle) {
- udat_applyPattern(icudf, false, NULL, 0);
+ if (wantRelative && !hasFormat && kCFDateFormatterNoStyle != df->_dateStyle) {
+ UErrorCode s = U_ZERO_ERROR;
+ udat_applyPatternRelative(icudf, NULL, 0, NULL, 0, &s);
+ } else {
+ udat_applyPattern(icudf, false, NULL, 0);
+ }
}
CFStringRef calident = (CFStringRef)CFLocaleGetValue(df->_locale, kCFLocaleCalendarIdentifierKey);
if (calident && CFEqual(calident, kCFCalendarIdentifierGregorian)) {
__CFDateFormatterCustomize(df);
- UChar ubuffer[BUFFER_SIZE];
- status = U_ZERO_ERROR;
- int32_t ret = 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);
- CFIndex cnt = CFStringGetLength(formatString);
- CFAssert1(cnt <= 1024, __kCFLogAssertion, "%s(): format string too long", __PRETTY_FUNCTION__);
- if (df->_format != formatString && cnt <= 1024) {
- STACK_BUFFER_DECL(UChar, ubuffer, cnt);
- const UChar *ustr = (UChar *)CFStringGetCharactersPtr((CFStringRef)formatString);
- if (NULL == ustr) {
- CFStringGetCharacters(formatString, CFRangeMake(0, cnt), (UniChar *)ubuffer);
- ustr = ubuffer;
+ 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;
+ 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);
+ CFStringRef formatString = __CFDateFormatterCreateForcedString(df, newFormat);
+ CFIndex cnt = CFStringGetLength(formatString);
+ CFAssert1(cnt <= BUFFER_SIZE, __kCFLogAssertion, "%s(): time format string too long", __PRETTY_FUNCTION__);
+ if (cnt <= BUFFER_SIZE) {
+ CFStringGetCharacters(formatString, CFRangeMake(0, cnt), (UniChar *)timeBuffer);
+ timeLen = cnt;
+ status = U_ZERO_ERROR;
+ 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
+ if (U_SUCCESS(status) && ret <= BUFFER_SIZE) {
+ if (df->_format) CFRelease(df->_format);
+ df->_format = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (const UniChar *)ubuffer, ret);
+ }
}
- UErrorCode status = U_ZERO_ERROR;
+ CFRelease(formatString);
+ CFRelease(newFormat);
+ }
+ } else {
+ UChar ubuffer[BUFFER_SIZE];
+ status = U_ZERO_ERROR;
+ int32_t ret = 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);
+ CFIndex cnt = CFStringGetLength(formatString);
+ CFAssert1(cnt <= 1024, __kCFLogAssertion, "%s(): format string too long", __PRETTY_FUNCTION__);
+ if (df->_format != formatString && cnt <= 1024) {
+ STACK_BUFFER_DECL(UChar, ubuffer, cnt);
+ const UChar *ustr = (UChar *)CFStringGetCharactersPtr((CFStringRef)formatString);
+ if (NULL == ustr) {
+ CFStringGetCharacters(formatString, CFRangeMake(0, cnt), (UniChar *)ubuffer);
+ ustr = ubuffer;
+ }
+ UErrorCode status = U_ZERO_ERROR;
// udat_applyPattern(df->_df, false, ustr, cnt, &status);
- udat_applyPattern(df->_df, false, ustr, cnt);
- if (U_SUCCESS(status)) {
- if (df->_format) CFRelease(df->_format);
- df->_format = (CFStringRef)CFStringCreateCopy(CFGetAllocator(df), formatString);
+ udat_applyPattern(df->_df, false, ustr, cnt);
+ if (U_SUCCESS(status)) {
+ if (df->_format) CFRelease(df->_format);
+ df->_format = (CFStringRef)CFStringCreateCopy(CFGetAllocator(df), formatString);
+ }
}
+ CFRelease(formatString);
+ CFRelease(newFormat);
}
- CFRelease(formatString);
- CFRelease(newFormat);
}
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);
RESET_PROPERTY(_ShortStandaloneQuarterSymbols, kCFDateFormatterShortStandaloneQuarterSymbolsKey);
RESET_PROPERTY(_AMSymbol, kCFDateFormatterAMSymbolKey);
RESET_PROPERTY(_PMSymbol, kCFDateFormatterPMSymbolKey);
+ RESET_PROPERTY(_AmbiguousYearStrategy, kCFDateFormatterAmbiguousYearStrategyKey);
}
static CFTypeID __kCFDateFormatterTypeID = _kCFRuntimeNotATypeID;
__CFDateFormatterDeallocate,
NULL,
NULL,
- NULL, //
+ NULL, //
__CFDateFormatterCopyDescription
};
memory->_property._ShortStandaloneQuarterSymbols = NULL;
memory->_property._AMSymbol = NULL;
memory->_property._PMSymbol = NULL;
+ memory->_property._AmbiguousYearStrategy = NULL;
switch (dateStyle) {
case kCFDateFormatterNoStyle:
}
if (emit) CFStringAppendCharacters(outString, &ch, 1);
}
-
+
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) {
+ if (wantRelative && !hasFormat && kCFDateFormatterNoStyle != formatter->_dateStyle) {
__substituteFormatStringFromPrefsDFRelative(formatter);
} else {
__substituteFormatStringFromPrefsDF(formatter, false);
// the whole UDateFormat.
if (formatter->_property._HasCustomFormat != kCFBooleanTrue && formatter->_property._DoesRelativeDateFormatting == kCFBooleanTrue) {
__ResetUDateFormat(formatter, true);
+ // the "true" results in: if you set a custom format string, you don't get relative date formatting
}
STACK_BUFFER_DECL(UChar, ubuffer, cnt);
const UChar *ustr = (UChar *)CFStringGetCharactersPtr((CFStringRef)formatString);
return string;
}
+static UDate __CFDateFormatterCorrectTimeWithTarget(UCalendar *calendar, UDate at, int32_t target, Boolean isEra, UErrorCode *status) {
+ ucal_setMillis(calendar, at, status);
+ UCalendarDateFields field = isEra ? UCAL_ERA : UCAL_YEAR;
+ ucal_set(calendar, field, target);
+ return 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);
+ UCalendarDateFields field = isEra ? UCAL_ERA : UCAL_YEAR;
+ int32_t currEraOrCentury = ucal_get(calendar, field, status);
+ if (!isEra) {
+ currYear %= 100;
+ currEraOrCentury = currEraOrCentury / 100 * 100; // get century
+ }
+
+ CFIndex futureMax = currYear + futureYears;
+ CFIndex pastMin = currYear - pastYears;
+
+ CFRange currRange, futureRange, pastRange;
+ currRange.location = futureRange.location = pastRange.location = kCFNotFound;
+ currRange.length = futureRange.length = pastRange.length = 0;
+ if (!isEra) {
+ if (period < INT_MAX && futureMax >= period) {
+ futureRange.location = 0;
+ futureRange.length = futureMax - period + 1;
+ }
+ if (pastMin < 0) {
+ pastRange.location = period + pastMin;
+ pastRange.length = period - pastRange.location;
+ }
+ if (pastRange.location != kCFNotFound) {
+ currRange.location = 0;
+ } else {
+ currRange.location = pastMin;
+ }
+ } else {
+ if (period < INT_MAX && futureMax > period) {
+ futureRange.location = 1,
+ futureRange.length = futureMax - period;
+ }
+ if (pastMin <= 0) {
+ pastRange.location = period + pastMin;
+ pastRange.length = period - pastRange.location + 1;
+ }
+ if (pastRange.location != kCFNotFound) {
+ currRange.location = 1;
+ } else {
+ currRange.location = pastMin;
+ }
+
+ }
+ currRange.length = period - pastRange.length - futureRange.length;
+
+ ucal_setMillis(calendar, at, status);
+ int32_t atYear = ucal_get(calendar, UCAL_YEAR, status);
+ if (!isEra) {
+ atYear %= 100;
+ currEraOrCentury += atYear;
+ }
+
+ int32_t offset = 0; // current era or century
+ if (pastRange.location != kCFNotFound && atYear >= pastRange.location && atYear - pastRange.location + 1 <= pastRange.length) {
+ offset = -1; // past era or century
+ } else if (futureRange.location != kCFNotFound && atYear >= futureRange.location && atYear - futureRange.location + 1 <= futureRange.length) {
+ offset = 1; // next era or century
+ }
+ if (!isEra) offset *= 100;
+ return __CFDateFormatterCorrectTimeWithTarget(calendar, at, currEraOrCentury+offset, isEra, status);
+}
+
+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);
+ return years+1;
+}
+
+static Boolean __CFDateFormatterHandleAmbiguousYear(CFDateFormatterRef formatter, CFStringRef calendar_id, UDateFormat *df, UCalendar *cal, UDate *at, const UChar *ustr, CFIndex length, UErrorCode *status) {
+ Boolean success = true;
+ int64_t ambigStrat = kCFDateFormatterAmbiguousYearAssumeToNone;
+ if (formatter->_property._AmbiguousYearStrategy) {
+ CFNumberGetValue(formatter->_property._AmbiguousYearStrategy, kCFNumberSInt64Type, &ambigStrat);
+ }
+ 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) {
+ switch (ambigStrat) {
+ case kCFDateFormatterAmbiguousYearFailToParse:
+ success = false;
+ break;
+ case kCFDateFormatterAmbiguousYearAssumeToCurrent: {
+ ucal_setMillis(cal, ucal_getNow(), status);
+ int32_t currEra = ucal_get(cal, UCAL_ERA, status);
+ *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, currEra, true, status);
+ break;
+ }
+ case kCFDateFormatterAmbiguousYearAssumeToCenteredAroundCurrentDate:
+ *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 60, 29, 30, true, status);
+ break;
+ case kCFDateFormatterAmbiguousYearAssumeToFuture:
+ *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 60, 0, 59, true, status);
+ break;
+ case kCFDateFormatterAmbiguousYearAssumeToPast:
+ *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 60, 59, 0, true, status);
+ break;
+ case kCFDateFormatterAmbiguousYearAssumeToLikelyFuture:
+ *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 60, 10, 49, true, status);
+ break;
+ case kCFDateFormatterAmbiguousYearAssumeToLikelyPast:
+ *at = __CFDateFormatterCorrectTimeToARangeAroundCurrentDate(cal, *at, 60, 49, 10, true, status);
+ break;
+ case kCFDateFormatterAmbiguousYearAssumeToNone:
+ default:
+ break; // do nothing
+ }
+ }
+ } 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 (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);
+ switch (ambigStrat) {
+ case kCFDateFormatterAmbiguousYearFailToParse:
+ success = false;
+ break;
+ 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;
+ } else { // current era
+ *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, currEra, true, status);
+ }
+ break;
+ case kCFDateFormatterAmbiguousYearAssumeToPast:
+ if (givenYear > currYear) { // past era
+ success = false;
+ // we find the closest era that has the given year
+ // if no era has such given year, we fail the parse
+ for (CFIndex era = currEra-1; era >= 234; era--) { // Showa era (234) is the longest era
+ int32_t years = __CFDateFormatterGetMaxYearGivenJapaneseEra(cal, era, status);
+ if (givenYear > years) {
+ continue;
+ }
+ success = true;
+ *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, era, true, status);
+ break;
+ }
+ } else { // current era
+ *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, currEra, true, status);
+ }
+ break;
+ case kCFDateFormatterAmbiguousYearAssumeToLikelyFuture:
+ if (givenYear < currYear - 10) { // we allow 10 years to the past
+ success = false;
+ } else {
+ *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, currEra, true, status);
+ }
+ break;
+ case kCFDateFormatterAmbiguousYearAssumeToLikelyPast:
+ if (givenYear > currYear + 10) {
+ success = false;
+ // we find the closest era that has the given year
+ // if no era has such given year, we fail the parse
+ for (CFIndex era = currEra-1; era >= 234; era--) { // Showa era (234) is the longest era
+ int32_t years = __CFDateFormatterGetMaxYearGivenJapaneseEra(cal, era, status);
+ if (givenYear > years) {
+ continue;
+ }
+ success = true;
+ *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, era, true, status);
+ break;
+ }
+ } else { // current era
+ *at = __CFDateFormatterCorrectTimeWithTarget(cal, *at, currEra, true, status);
+ }
+ break;
+ case kCFDateFormatterAmbiguousYearAssumeToNone:
+ default:
+ break; // do nothing
+ }
+ }
+ } 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);
+ }
+ break; // do nothing
+ }
+ }
+
+ }
+ return success;
+}
+
CFDateRef CFDateFormatterCreateDateFromString(CFAllocatorRef allocator, CFDateFormatterRef formatter, CFStringRef string, CFRange *rangep) {
if (allocator == NULL) allocator = __CFGetDefaultAllocator();
__CFGenericValidateType(allocator, CFAllocatorGetTypeID());
UDate udate;
int32_t dpos = 0;
UErrorCode status = U_ZERO_ERROR;
+ UDateFormat *df2 = udat_clone(formatter->_df, &status);
+ UCalendar *cal2 = (UCalendar *)udat_getCalendar(df2);
+ 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);
+ } 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
+ } 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);
+ }
if (formatter->_property._DefaultDate) {
CFAbsoluteTime at = CFDateGetAbsoluteTime(formatter->_property._DefaultDate);
udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0;
- UDateFormat *df2 = udat_clone(formatter->_df, &status);
- UCalendar *cal2 = (UCalendar *)udat_getCalendar(df2);
ucal_setMillis(cal2, udate, &status);
- udat_parseCalendar(formatter->_df, cal2, ustr, range.length, &dpos, &status);
- udate = ucal_getMillis(cal2, &status);
- udat_close(df2);
- } else {
- udate = udat_parse(formatter->_df, ustr, range.length, &dpos, &status);
}
+ udat_parseCalendar(df2, cal2, ustr, range.length, &dpos, &status);
+ udate = ucal_getMillis(cal2, &status);
if (rangep) rangep->length = dpos;
- if (U_FAILURE(status)) {
- return false;
- }
- if (atp) {
- *atp = (double)udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970;
+ 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 (atp) {
+ *atp = (double)udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970;
+ }
+ success = true;
}
- return true;
+ CFRelease(calendar_id);
+ udat_close(df2);
+ return success;
}
static void __CFDateFormatterSetSymbolsArray(UDateFormat *icudf, int32_t icucode, int index_base, CFTypeRef value) {
if (!directToICU) {
formatter->_property. _PMSymbol = (CFStringRef)CFDateFormatterCopyProperty(formatter, kCFDateFormatterPMSymbolKey);
}
+ } else if (kCFDateFormatterAmbiguousYearStrategyKey == key) {
+ oldProperty = formatter->_property._AmbiguousYearStrategy;
+ formatter->_property._AmbiguousYearStrategy = NULL;
+ __CFGenericValidateType(value, CFNumberGetTypeID());
+ formatter->_property._AmbiguousYearStrategy = (CFNumberRef)CFRetain(value);
} else {
CFAssert3(0, __kCFLogAssertion, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__, key, key);
}
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);
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 {
CFAssert3(0, __kCFLogAssertion, "%s(): unknown key %p (%@)", __PRETTY_FUNCTION__, key, key);
}
*/
/* CFDateFormatter.h
- Copyright (c) 2003-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2003-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFDATEFORMATTER__)
CF_EXPORT
CFTypeID CFDateFormatterGetTypeID(void);
-enum { // date and time format styles
+typedef CF_ENUM(CFIndex, CFDateFormatterStyle) { // date and time format styles
kCFDateFormatterNoStyle = 0,
kCFDateFormatterShortStyle = 1,
kCFDateFormatterMediumStyle = 2,
kCFDateFormatterLongStyle = 3,
kCFDateFormatterFullStyle = 4
};
-typedef CFIndex CFDateFormatterStyle;
// The exact formatted result for these date and time styles depends on the
// locale, but generally:
// const CFStringRef kCFRepublicOfChinaCalendar;
// const CFStringRef kCFPersianCalendar;
// const CFStringRef kCFIndianCalendar;
-// const CFStringRef kCFISO8601Calendar; not yet implemented
+// const CFStringRef kCFISO8601Calendar;
CF_EXTERN_C_END
*/
/* CFDictionary.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
Machine generated from Notes/HashingCode.template
*/
#include "CFBasicHash.h"
#include <CoreFoundation/CFString.h>
+
#define CFDictionary 0
#define CFSet 0
#define CFBag 0
} else {
newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0);
}
- if (!newcb) HALT;
+ if (!newcb) return NULL;
memmove(newcb, (void *)cb, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *));
return newcb;
}
} else {
newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0);
}
- if (!newcb) HALT;
+ if (!newcb) return NULL;
newcb->copyCallbacks = __CFDictionaryCopyCallbacks;
newcb->freeCallbacks = __CFDictionaryFreeCallbacks;
newcb->retainValue = __CFDictionaryRetainValue;
}
CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb);
- CFBasicHashSetSpecialBits(ht, specialBits);
+ if (ht) CFBasicHashSetSpecialBits(ht, specialBits);
+ if (!ht && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, cb);
return ht;
}
CFTypeID typeID = CFDictionaryGetTypeID();
CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
CFBasicHashRef ht = __CFDictionaryCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
+ if (!ht) return NULL;
if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
for (CFIndex idx = 0; idx < numValues; idx++) {
CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
CFTypeID typeID = CFDictionaryGetTypeID();
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);
if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (mutable)");
CFDictionaryGetKeysAndValues(other, klist, vlist);
#endif
ht = __CFDictionaryCreateGeneric(allocator, & kCFTypeDictionaryKeyCallBacks, CFDictionary ? & kCFTypeDictionaryValueCallBacks : NULL, CFDictionary);
- if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
- for (CFIndex idx = 0; idx < numValues; idx++) {
+ if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+ for (CFIndex idx = 0; ht && idx < numValues; idx++) {
CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
}
if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
} else {
ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
}
+ if (!ht) return NULL;
CFBasicHashMakeImmutable(ht);
*(uintptr_t *)ht = __CFISAForTypeID(typeID);
_CFRuntimeSetInstanceTypeID(ht, typeID);
CFDictionaryGetKeysAndValues(other, klist, vlist);
#endif
ht = __CFDictionaryCreateGeneric(allocator, & kCFTypeDictionaryKeyCallBacks, CFDictionary ? & kCFTypeDictionaryValueCallBacks : NULL, CFDictionary);
- if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
- for (CFIndex idx = 0; idx < numValues; idx++) {
+ if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+ for (CFIndex idx = 0; ht && idx < numValues; idx++) {
CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
}
if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
} else {
ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
}
+ if (!ht) return NULL;
*(uintptr_t *)ht = __CFISAForTypeID(typeID);
_CFRuntimeSetInstanceTypeID(ht, typeID);
if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFDictionary (mutable)");
}
CFIndex CFDictionaryGetCount(CFHashRef hc) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, CFIndex, hc, "count");
- if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, CFIndex, hc, "count");
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSDictionary *)hc, count);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSSet *)hc, count);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
return CFBasicHashGetCount((CFBasicHashRef)hc);
}
#if CFSet || CFBag
CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t key) {
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, CFIndex, hc, "countForKey:", key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, CFIndex, hc, "countForObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSDictionary *)hc, countForKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSSet *)hc, countForObject:(id)key);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key);
}
#if CFSet || CFBag
Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t key) {
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, char, hc, "containsKey:", key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, char, hc, "containsObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, char, (NSDictionary *)hc, containsKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, char, (NSSet *)hc, containsObject:(id)key);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key));
}
const_any_pointer_t CFDictionaryGetValue(CFHashRef hc, const_any_pointer_t key) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, const_any_pointer_t, hc, "objectForKey:", key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, const_any_pointer_t, hc, "member:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, const_any_pointer_t, (NSSet *)hc, member:(id)key);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0);
}
Boolean CFDictionaryGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, Boolean, hc, "__getValue:forKey:", (any_t *)value, key);
- if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, Boolean, hc, "__getValue:forObj:", (any_t *)value, key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
if (0 < bkt.count) {
#if CFDictionary
CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
- CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, CFIndex, hc, "countForObject:", value);
+ CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, CFIndex, (NSDictionary *)hc, countForObject:(id)value);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value);
}
Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) {
- CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, char, hc, "containsObject:", value);
+ CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, char, (NSDictionary *)hc, containsObject:(id)value);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value));
}
CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
- CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, Boolean, hc, "getActualKey:forKey:", actualkey, key);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
if (0 < bkt.count) {
void CFDictionaryGetValues(CFHashRef hc, const_any_pointer_t *keybuf) {
const_any_pointer_t *valuebuf = 0;
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "getObjects:andKeys:", (any_t *)valuebuf, (any_t *)keybuf);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "getObjects:", (any_t *)keybuf);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSSet *)hc, getObjects:(id *)keybuf);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
if (kCFUseCollectableAllocator) {
CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc);
void CFDictionaryApplyFunction(CFHashRef hc, CFDictionaryApplierFunction applier, any_pointer_t context) {
FAULT_CALLBACK((void **)&(applier));
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "__apply:context:", applier, context);
- if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "__applyValues:context:", applier, context);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSDictionary *)hc, __apply:(void (*)(const void *, const void *, void *))applier context:(void *)context);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
#if CFDictionary
void CFDictionaryAddValue(CFMutableHashRef hc, const_any_pointer_t key) {
const_any_pointer_t value = key;
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "addObject:forKey:", value, key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "addObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, addObject:(id)key);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
void CFDictionaryReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) {
const_any_pointer_t value = key;
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "replaceObject:forKey:", value, key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "replaceObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, replaceObject:(id)value forKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, replaceObject:(id)key);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
void CFDictionarySetValue(CFMutableHashRef hc, const_any_pointer_t key) {
const_any_pointer_t value = key;
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFDictionaryTypeID, void, hc, "setObject:forKey:", value, key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "setObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, __setObject:(id)value forKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, setObject:(id)key);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
}
void CFDictionaryRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "removeObjectForKey:", key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFDictionaryTypeID, void, hc, "removeObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, removeObject:(id)key);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
}
void CFDictionaryRemoveAllValues(CFMutableHashRef hc) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, void, hc, "removeAllObjects");
- if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFDictionaryTypeID, void, hc, "removeAllObjects");
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableDictionary *)hc, removeAllObjects);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFDictionaryTypeID, void, (NSMutableSet *)hc, removeAllObjects);
__CFGenericValidateType(hc, __kCFDictionaryTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
*/
/* CFDictionary.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
/*!
#include <CoreFoundation/CFBase.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
/*!
void CFDictionaryRemoveAllValues(CFMutableDictionaryRef theDict);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFDICTIONARY__ */
*/
/* CFError.c
- Copyright (c) 2006-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2006-2012, Apple Inc. All rights reserved.
Responsibility: Ali Ozer
*/
#include <mach/mach_error.h>
#endif
+
/* Pre-defined userInfo keys
*/
CONST_STRING_DECL(kCFErrorLocalizedDescriptionKey, "NSLocalizedDescription");
/* A non-retained accessor for the userInfo. Might return NULL in some cases, if the subclass of NSError returned nil for some reason. It works with a CF or NSError.
*/
static CFDictionaryRef _CFErrorGetUserInfo(CFErrorRef err) {
- CF_OBJC_FUNCDISPATCH0(__kCFErrorTypeID, CFDictionaryRef, err, "userInfo");
+ CF_OBJC_FUNCDISPATCHV(__kCFErrorTypeID, CFDictionaryRef, (NSError *)err, userInfo);
__CFAssertIsError(err);
return err->userInfo;
}
CFStringAppendFormat(result, NULL, CFSTR("Error Domain=%@ Code=%d"), CFErrorGetDomain(err), (long)CFErrorGetCode(err));
CFStringAppendFormat(result, NULL, CFSTR(" \"%@\""), desc);
if (debugDesc && CFStringGetLength(debugDesc) > 0) CFStringAppendFormat(result, NULL, CFSTR(" (%@)"), debugDesc);
- if (userInfo) {
+ if (userInfo && CFDictionaryGetCount(userInfo)) {
CFStringAppendFormat(result, NULL, CFSTR(" UserInfo=%p {"), userInfo);
CFDictionaryApplyFunction(userInfo, userInfoKeyValueShow, (void *)result);
CFIndex commaLength = (CFStringHasSuffix(result, CFSTR(", "))) ? 2 : 0;
}
CFStringRef CFErrorGetDomain(CFErrorRef err) {
- CF_OBJC_FUNCDISPATCH0(__kCFErrorTypeID, CFStringRef, err, "domain");
+ CF_OBJC_FUNCDISPATCHV(__kCFErrorTypeID, CFStringRef, (NSError *)err, domain);
__CFAssertIsError(err);
return err->domain;
}
CFIndex CFErrorGetCode(CFErrorRef err) {
- CF_OBJC_FUNCDISPATCH0(__kCFErrorTypeID, CFIndex, err, "code");
+ CF_OBJC_FUNCDISPATCHV(__kCFErrorTypeID, CFIndex, (NSError *)err, code);
__CFAssertIsError(err);
return err->code;
}
CFStringRef CFErrorCopyDescription(CFErrorRef err) {
if (CF_IS_OBJC(__kCFErrorTypeID, err)) { // Since we have to return a retained result, we need to treat the toll-free bridging specially
- CFStringRef desc;
- CF_OBJC_CALL0(CFStringRef, desc, err, "localizedDescription");
+ CFStringRef desc = (CFStringRef) CF_OBJC_CALLV((NSError *)err, localizedDescription);
return desc ? (CFStringRef)CFRetain(desc) : NULL; // !!! It really should never return nil.
}
__CFAssertIsError(err);
CFStringRef CFErrorCopyFailureReason(CFErrorRef err) {
if (CF_IS_OBJC(__kCFErrorTypeID, err)) { // Since we have to return a retained result, we need to treat the toll-free bridging specially
- CFStringRef str;
- CF_OBJC_CALL0(CFStringRef, str, err, "localizedFailureReason");
+ CFStringRef str = (CFStringRef) CF_OBJC_CALLV((NSError *)err, localizedFailureReason);
return str ? (CFStringRef)CFRetain(str) : NULL; // It's possible for localizedFailureReason to return nil
}
__CFAssertIsError(err);
CFStringRef CFErrorCopyRecoverySuggestion(CFErrorRef err) {
if (CF_IS_OBJC(__kCFErrorTypeID, err)) { // Since we have to return a retained result, we need to treat the toll-free bridging specially
- CFStringRef str;
- CF_OBJC_CALL0(CFStringRef, str, err, "localizedRecoverySuggestion");
+ CFStringRef str = (CFStringRef) CF_OBJC_CALLV((NSError *)err, localizedRecoverySuggestion);
return str ? (CFStringRef)CFRetain(str) : NULL; // It's possible for localizedRecoverySuggestion to return nil
}
__CFAssertIsError(err);
CFArrayRef paths = CFCopySearchPathForDirectoriesInDomains(kCFLibraryDirectory, kCFSystemDomainMask, false);
if (paths) {
if (CFArrayGetCount(paths) > 0) {
- CFStringRef path = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@/CoreServices/CoreTypes.bundle"), CFArrayGetValueAtIndex(paths, 0));
- CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, path, kCFURLPOSIXPathStyle, false /* not a directory */);
- if (url) {
- CFBundleRef bundle = CFBundleCreate(kCFAllocatorSystemDefault, url);
- if (bundle) {
- // We only want to return a result if there was a localization
- CFStringRef localizedErrStr = CFBundleCopyLocalizedString(bundle, errStr, errStr, CFSTR("ErrnoErrors"));
- if (localizedErrStr == errStr) {
- CFRelease(localizedErrStr);
- CFRelease(errStr);
- errStr = NULL;
- } else {
- CFRelease(errStr);
- errStr = localizedErrStr;
- }
- CFRelease(bundle);
- }
- CFRelease(url);
- }
- CFRelease(path);
+ CFStringRef fileSystemPath = CFURLCopyFileSystemPath((CFURLRef)CFArrayGetValueAtIndex(paths, 0), kCFURLPOSIXPathStyle);
+ if (fileSystemPath) {
+ CFStringRef path = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@/CoreServices/CoreTypes.bundle"), fileSystemPath);
+ CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, path, kCFURLPOSIXPathStyle, false /* not a directory */);
+ CFRelease(fileSystemPath);
+ if (url) {
+ CFBundleRef bundle = CFBundleCreate(kCFAllocatorSystemDefault, url);
+ if (bundle) {
+ // We only want to return a result if there was a localization
+ CFStringRef localizedErrStr = CFBundleCopyLocalizedString(bundle, errStr, errStr, CFSTR("ErrnoErrors"));
+ if (localizedErrStr == errStr) {
+ CFRelease(localizedErrStr);
+ CFRelease(errStr);
+ errStr = NULL;
+ } else {
+ CFRelease(errStr);
+ errStr = localizedErrStr;
+ }
+ CFRelease(bundle);
+ }
+ CFRelease(url);
+ }
+ CFRelease(path);
+ }
}
CFRelease(paths);
}
if (!_CFErrorCallBackTable) _CFErrorInitializeCallBackTable();
__CFSpinLock(&_CFErrorSpinlock);
if (callBack) {
- CFDictionarySetValue(_CFErrorCallBackTable, domainName, callBack);
+ CFDictionarySetValue(_CFErrorCallBackTable, domainName, (void *)callBack);
} else {
CFDictionaryRemoveValue(_CFErrorCallBackTable, domainName);
}
*/
/* CFError.h
- Copyright (c) 2006-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2006-2012, Apple Inc. All rights reserved.
*/
/*!
#include <CoreFoundation/CFString.h>
#include <CoreFoundation/CFDictionary.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
/*!
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFERROR__ */
*/
/* CFError_Private.h
- Copyright (c) 2006-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2006-2012, Apple Inc. All rights reserved.
This is Apple-internal SPI for CFError.
*/
*/
/* CFFileUtilities.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Tony Parker
*/
#include "CFInternal.h"
#include <CoreFoundation/CFPriv.h>
+
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
#if DEPLOYMENT_TARGET_WINDOWS
#include <io.h>
#include <fcntl.h>
-#include <sys/stat.h>
-#include <errno.h>
#define close _close
#define write _write
#define statinfo _stat
#else
- #include <string.h>
- #include <unistd.h>
- #include <dirent.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <pwd.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <stdio.h>
+
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <fcntl.h>
#define statinfo stat
}
CF_INLINE void closeAutoFSNoWait(int fd) {
-#if DEPLOYMENT_TARGET_WINDOWS
-#else
if (-1 != fd) close(fd);
-#endif
}
__private_extern__ CFStringRef _CFCopyExtensionForAbstractType(CFStringRef abstractType) {
return ret;
}
-#if DEPLOYMENT_TARGET_WINDOWS
-// todo: remove this function and make callers use _CFCreateDirectory
-__private_extern__ Boolean _CFCreateDirectoryWide(const wchar_t *path) {
- return CreateDirectoryW(path, 0);
-}
-#endif
-
__private_extern__ Boolean _CFRemoveDirectory(const char *path) {
int no_hang_fd = openAutoFSNoWait();
int ret = ((rmdir(path) == 0) ? true : false);
return ret;
}
-__private_extern__ Boolean _CFReadBytesFromFile(CFAllocatorRef alloc, CFURLRef url, void **bytes, CFIndex *length, CFIndex maxLength) {
- // maxLength is the number of bytes desired, or 0 if the whole file is desired regardless of length.
- int fd = -1;
+__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.
struct statinfo statBuf;
- char path[CFMaxPathSize];
- if (!CFURLGetFileSystemRepresentation(url, true, (uint8_t *)path, CFMaxPathSize)) {
- return false;
- }
-
+
*bytes = NULL;
-
+
int no_hang_fd = openAutoFSNoWait();
- fd = open(path, O_RDONLY|CF_OPENFLGS, 0666);
-
- if (fd < 0) {
+ *fd = open(path, O_RDONLY|extraOpenFlags|CF_OPENFLGS, 0666);
+
+ if (*fd < 0) {
closeAutoFSNoWait(no_hang_fd);
return false;
}
- if (fstat(fd, &statBuf) < 0) {
+ if (fstat(*fd, &statBuf) < 0) {
int saveerr = thread_errno();
- close(fd);
+ close(*fd);
+ *fd = -1;
closeAutoFSNoWait(no_hang_fd);
thread_set_errno(saveerr);
return false;
}
if ((statBuf.st_mode & S_IFMT) != S_IFREG) {
- close(fd);
+ close(*fd);
+ *fd = -1;
closeAutoFSNoWait(no_hang_fd);
thread_set_errno(EACCES);
return false;
}
*bytes = CFAllocatorAllocate(alloc, desiredLength, 0);
if (__CFOASafe) __CFSetLastAllocationEventName(*bytes, "CFUtilities (file-bytes)");
-// fcntl(fd, F_NOCACHE, 1);
- if (read(fd, *bytes, desiredLength) < 0) {
+ // fcntl(fd, F_NOCACHE, 1);
+ if (read(*fd, *bytes, desiredLength) < 0) {
CFAllocatorDeallocate(alloc, *bytes);
- close(fd);
- closeAutoFSNoWait(no_hang_fd);
+ close(*fd);
+ *fd = -1;
+ closeAutoFSNoWait(no_hang_fd);
return false;
}
*length = desiredLength;
}
- close(fd);
closeAutoFSNoWait(no_hang_fd);
return true;
}
+__private_extern__ 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) {
+ close(fd);
+ }
+ return result;
+}
+__private_extern__ 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];
+ if (!CFURLGetFileSystemRepresentation(url, true, (uint8_t *)path, CFMaxPathSize)) {
+ return false;
+ }
+ return _CFReadBytesFromPath(alloc, (const char *)path, bytes, length, maxLength, extraOpenFlags);
+}
+
__private_extern__ Boolean _CFWriteBytesToFile(CFURLRef url, const void *bytes, CFIndex length) {
int fd = -1;
int mode;
FindClose(handle);
pathBuf[pathLength] = '\0';
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
uint8_t extBuff[CFMaxPathSize];
int extBuffInteriorDotCount = 0; //people insist on using extensions like ".trace.plist", so we need to know how many dots back to look :(
dirURL = CFURLCreateFromFileSystemRepresentation(alloc, (uint8_t *)dirPath, pathLength, true);
releaseBase = true;
}
- if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN) {
+ if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN || dp->d_type == DT_LNK || dp->d_type == DT_WHT) {
Boolean isDir = (dp->d_type == DT_DIR);
if (!isDir) {
// Ugh; must stat.
}
-// MF:!!! Should pull in the rest of the UniChar based path utils from Foundation.
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
- #define UNIX_PATH_SEMANTICS
-#elif DEPLOYMENT_TARGET_WINDOWS
- #define WINDOWS_PATH_SEMANTICS
+#if DEPLOYMENT_TARGET_WINDOWS
+#define WINDOWS_PATH_SEMANTICS
#else
-#error Unknown platform
+#define UNIX_PATH_SEMANTICS
#endif
#if defined(WINDOWS_PATH_SEMANTICS)
#define IS_SLASH(C) ((C) == ':')
#endif
+__private_extern__ UniChar _CFGetSlash(){
+ return CFPreferredSlash;
+}
+
__private_extern__ Boolean _CFIsAbsolutePath(UniChar *unichars, CFIndex length) {
if (length < 1) {
return false;
return ((0 < start) ? start : length);
}
-#undef CF_OPENFLGS
-#undef UNIX_PATH_SEMANTICS
-#undef WINDOWS_PATH_SEMANTICS
-#undef HFS_PATH_SEMANTICS
-#undef CFPreferredSlash
-#undef HAS_DRIVE
-#undef HAS_NET
-#undef IS_SLASH
*/
/* CFICUConverters.c
- Copyright (c) 2004-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2004-2012, Apple Inc. All rights reserved.
Responsibility: Aki Inoue
*/
#define MAX_BUFFER_SIZE (1000)
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#if (U_ICU_VERSION_MAJOR_NUM > 4) || ((U_ICU_VERSION_MAJOR_NUM == 4) && (U_ICU_VERSION_MINOR_NUM > 6))
+#if (U_ICU_VERSION_MAJOR_NUM > 49)
#warning Unknown ICU version. Check binary compatibility issues for rdar://problem/6024743
#endif
#endif
* CoreFoundation
*
* Created by Aki Inoue on 07/12/04.
- * Copyright (c) 2007-2011, Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2012, Apple Inc. All rights reserved.
*
*/
*/
/* CFInternal.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
/*
#include <CoreFoundation/CFLogUtilities.h>
#include <CoreFoundation/CFRuntime.h>
#include <limits.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
#include <xlocale.h>
#include <unistd.h>
-#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
#include <sys/time.h>
-#include <pthread.h>
#include <signal.h>
#endif
-#if DEPLOYMENT_TARGET_WINDOWS
#include <pthread.h>
-#endif
#if defined(__BIG_ENDIAN__)
CF_EXPORT CFStringRef _CFStringCreateHostName(void);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#include <CoreFoundation/CFRunLoop.h>
CF_EXPORT void _CFMachPortInstallNotifyPort(CFRunLoopRef rl, CFStringRef mode);
#endif
__private_extern__ CFIndex __CFActiveProcessorCount();
-#if defined(__ppc__)
- #define HALT do {asm __volatile__("trap"); kill(getpid(), 9); } while (0)
-#elif defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__)
#if defined(__GNUC__)
#define HALT do {asm __volatile__("int3"); kill(getpid(), 9); } while (0)
#elif defined(_MSC_VER)
#error Compiler not supported
#endif
#endif
-#if defined(__arm__)
- #define HALT do {asm __volatile__("bkpt 0xCF"); kill(getpid(), 9); } while (0)
-#endif
+
#if defined(DEBUG)
#define __CFAssert(cond, prio, desc, a1, a2, a3, a4, a5) \
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);
/* result is long long or int, depending on doLonglong
*/
extern const char *__CFgetenv(const char *n);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
-#define STACK_BUFFER_DECL(T, N, C) T N[C]
-#elif DEPLOYMENT_TARGET_WINDOWS
+// 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))
#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
+#define STACK_BUFFER_DECL(T, N, C) T N[C]
#endif
/* CFNetwork also has a copy of the CONST_STRING_DECL macro (for use on platforms without constant string support in cc); please warn cfnetwork-core@group.apple.com of any necessary changes to this macro. -- REW, 1/28/2002 */
-#if __CF_BIG_ENDIAN__ && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX)
+#if __CF_BIG_ENDIAN__
+
#define CONST_STRING_DECL(S, V) \
static struct CF_CONST_STRING __ ## S ## __ = {{(uintptr_t)&__CFConstantStringClassReference, {0x00, 0x00, 0x07, 0xc8}}, (uint8_t *)V, sizeof(V) - 1}; \
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 ## __;
-#elif __CF_LITTLE_ENDIAN__ && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX)
-#define CONST_STRING_DECL(S, V) \
-static struct CF_CONST_STRING __ ## S ## __ = {{(uintptr_t)&__CFConstantStringClassReference, {0xc8, 0x07, 0x00, 0x00}}, (uint8_t *)V, sizeof(V) - 1}; \
-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 ## __;
-#elif DEPLOYMENT_TARGET_WINDOWS
+
+#elif __CF_LITTLE_ENDIAN__
+
#define CONST_STRING_DECL(S, V) \
static struct CF_CONST_STRING __ ## S ## __ = {{(uintptr_t)&__CFConstantStringClassReference, {0xc8, 0x07, 0x00, 0x00}}, (uint8_t *)(V), sizeof(V) - 1}; \
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 ## __;
-#endif // __BIG_ENDIAN__
-#endif // __CONSTANT_CFSTRINGS__
-
-/* Buffer size for file pathname */
-#if DEPLOYMENT_TARGET_WINDOWS
- #define CFMaxPathSize ((CFIndex)262)
- #define CFMaxPathLength ((CFIndex)260)
-#else
- #define CFMaxPathSize ((CFIndex)1026)
- #define CFMaxPathLength ((CFIndex)1024)
#endif
+#endif // __CONSTANT_CFSTRINGS__
+
CF_EXPORT bool __CFOASafe;
CF_EXPORT void __CFSetLastAllocationEventName(void *ptr, const char *classname);
} \
OSSpinLockTry(__lockp__); })
-#elif DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
typedef OSSpinLock CFSpinLock_t;
#define CF_SPINLOCK_INIT_FOR_STRUCTS(X) (X = CFSpinLockInit)
CF_INLINE void __CFSpinLock(volatile CFSpinLock_t *lock) {
- while (__sync_val_compare_and_swap(lock, ~0, 0) != 0) {
+ while (__sync_val_compare_and_swap(lock, 0, ~0) != 0) {
sleep(0);
}
}
}
CF_INLINE Boolean __CFSpinLockTry(volatile CFSpinLock_t *lock) {
- return (__sync_val_compare_and_swap(lock, ~0, 0) == 0);
+ return (__sync_val_compare_and_swap(lock, 0, ~0) == 0);
}
#else
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
extern uint8_t __CF120293;
extern uint8_t __CF120290;
extern void __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YOU_MUST_EXEC__(void);
#define HAS_FORKED() 0
#endif
-#if DEPLOYMENT_TARGET_WINDOWS
#include <errno.h>
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
-#include <sys/errno.h>
-#endif
#define thread_errno() errno
#define thread_set_errno(V) do {errno = (V);} while (0)
/* These functions all act on a c-strings which must be in the file system encoding. */
CF_EXPORT Boolean _CFCreateDirectory(const char *path);
-#if DEPLOYMENT_TARGET_WINDOWS
-CF_EXPORT Boolean _CFCreateDirectoryWide(const wchar_t *path);
-#endif
CF_EXPORT Boolean _CFRemoveDirectory(const char *path);
CF_EXPORT Boolean _CFDeleteFile(const char *path);
-CF_EXPORT Boolean _CFReadBytesFromFile(CFAllocatorRef alloc, CFURLRef url, void **bytes, CFIndex *length, CFIndex maxLength);
+CF_EXPORT Boolean _CFReadBytesFromPathAndGetFD(CFAllocatorRef alloc, const char *path, void **bytes, CFIndex *length, CFIndex maxLength, int extraOpenFlags, int *fd);
+CF_EXPORT Boolean _CFReadBytesFromPath(CFAllocatorRef alloc, const char *path, void **bytes, CFIndex *length, CFIndex maxLength, int extraOpenFlags);
+CF_EXPORT Boolean _CFReadBytesFromFile(CFAllocatorRef alloc, CFURLRef url, void **bytes, CFIndex *length, CFIndex maxLength, int extraOpenFlags);
/* resulting bytes are allocated from alloc which MUST be non-NULL. */
/* maxLength of zero means the whole file. Otherwise it sets a limit on the number of bytes read. */
CF_EXPORT Boolean _CFWriteBytesToFile(CFURLRef url, const void *bytes, CFIndex length);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-CF_EXPORT Boolean _CFWriteBytesToFileWithAtomicity(CFURLRef url, const void *bytes, unsigned int length, SInt32 mode, Boolean atomic);
-#endif
CF_EXPORT CFMutableArrayRef _CFContentsOfDirectory(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 */
/* ==================== Simple path manipulation ==================== */
/* These functions all act on a UniChar buffers. */
+CF_EXPORT UniChar _CFGetSlash();
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);
// to release (that's why this stuff is in CF*Internal*.h),
// as can the definition of type info vs payload above.
//
-#if defined(__x86_64__)
+#if __LP64__
#define CF_IS_TAGGED_OBJ(PTR) ((uintptr_t)(PTR) & 0x1)
#define CF_TAGGED_OBJ_TYPE(PTR) ((uintptr_t)(PTR) & 0xF)
#else
enum {
kCFTaggedObjectID_Invalid = 0,
- kCFTaggedObjectID_Undefined0 = (0 << 1) + 1,
- kCFTaggedObjectID_Integer = (1 << 1) + 1,
+ kCFTaggedObjectID_Atom = (0 << 1) + 1,
+ kCFTaggedObjectID_Undefined3 = (1 << 1) + 1,
kCFTaggedObjectID_Undefined2 = (2 << 1) + 1,
- kCFTaggedObjectID_Undefined3 = (3 << 1) + 1,
- kCFTaggedObjectID_Undefined4 = (4 << 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_DateTS = (7 << 1) + 1,
+ kCFTaggedObjectID_Undefined7 = (7 << 1) + 1,
};
}
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;
uintptr_t type_isa = (uintptr_t)(typeID < __CFRuntimeClassTableSize ? __CFRuntimeObjCClassTable[typeID] : 0);
if (cfisa == type_isa) return false;
return true;
+#else
+ return false;
+#endif
}
-#define STUB_CF_OBJC 1
-
-#if STUB_CF_OBJC
-
-#define CF_IS_OBJC(typeID, obj) (false)
-
-#define CF_OBJC_VOIDCALL0(obj, sel) do { } while (0)
-#define CF_OBJC_VOIDCALL1(obj, sel, a1) do { } while (0)
-#define CF_OBJC_VOIDCALL2(obj, sel, a1, a2) do { } while (0)
-#define CF_OBJC_CALL0(rettype, retvar, obj, sel) do { } while (0)
-#define CF_OBJC_CALL1(rettype, retvar, obj, sel, a1) do { } while (0)
-#define CF_OBJC_CALL2(rettype, retvar, obj, sel, a1, a2) do { } while (0)
-
-#define CF_OBJC_FUNCDISPATCH0(typeID, rettype, obj, sel) do { } while (0)
-#define CF_OBJC_FUNCDISPATCH1(typeID, rettype, obj, sel, a1) do { } while (0)
-#define CF_OBJC_FUNCDISPATCH2(typeID, rettype, obj, sel, a1, a2) do { } while (0)
-#define CF_OBJC_FUNCDISPATCH3(typeID, rettype, obj, sel, a1, a2, a3) do { } while (0)
-#define CF_OBJC_FUNCDISPATCH4(typeID, rettype, obj, sel, a1, a2, a3, a4) do { } while (0)
-#define CF_OBJC_FUNCDISPATCH5(typeID, rettype, obj, sel, a1, a2, a3, a4, a5) do { } while (0)
-
-#endif // STUB_CF_OBJC
+#define CF_OBJC_FUNCDISPATCHV(typeID, obj, ...) do { } while (0)
+#define CF_OBJC_CALLV(obj, ...) (0)
/* See comments in CFBase.c
*/
-#if SUPPORT_CFM
-extern void __CF_FAULT_CALLBACK(void **ptr);
-extern void *__CF_INVOKE_CALLBACK(void *, ...);
-#define FAULT_CALLBACK(V) __CF_FAULT_CALLBACK(V)
-#define INVOKE_CALLBACK1(P, A) (__CF_INVOKE_CALLBACK(P, A))
-#define INVOKE_CALLBACK2(P, A, B) (__CF_INVOKE_CALLBACK(P, A, B))
-#define INVOKE_CALLBACK3(P, A, B, C) (__CF_INVOKE_CALLBACK(P, A, B, C))
-#define INVOKE_CALLBACK4(P, A, B, C, D) (__CF_INVOKE_CALLBACK(P, A, B, C, D))
-#define INVOKE_CALLBACK5(P, A, B, C, D, E) (__CF_INVOKE_CALLBACK(P, A, B, C, D, E))
-#define UNFAULT_CALLBACK(V) do { V = (void *)((uintptr_t)V & ~0x3); } while (0)
-#else
#define FAULT_CALLBACK(V)
#define INVOKE_CALLBACK1(P, A) (P)(A)
#define INVOKE_CALLBACK2(P, A, B) (P)(A, B)
#define INVOKE_CALLBACK4(P, A, B, C, D) (P)(A, B, C, D)
#define INVOKE_CALLBACK5(P, A, B, C, D, E) (P)(A, B, C, D, E)
#define UNFAULT_CALLBACK(V) do { } while (0)
-#endif
/* For the support of functionality which needs CarbonCore or other frameworks */
// These macros define an upcall or weak "symbol-lookup" wrapper function.
}
#else
-
#define DEFINE_WEAK_CFNETWORK_FUNC(R, N, P, A, ...)
#define DEFINE_WEAK_CFNETWORK_FUNC_FAIL(R, N, P, A, ...)
-
#endif
-
-#if !defined(DEFINE_WEAK_CARBONCORE_FUNC)
#define DEFINE_WEAK_CARBONCORE_FUNC(R, N, P, A, ...)
-#endif
-#if !defined(DEFINE_WEAK_CORESERVICESINTERNAL_FUNC)
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+
+extern void *__CFLookupCoreServicesInternalFunction(const char *name);
+
+#define DEFINE_WEAK_CORESERVICESINTERNAL_FUNC(R, N, P, A, ...) \
+ static R __CFCoreServicesInternal_ ## N P { \
+ typedef R (*dyfuncptr)P; \
+ static dyfuncptr dyfunc = (dyfuncptr)(~(uintptr_t)0); \
+ if ((dyfuncptr)(~(uintptr_t)0) == dyfunc) { \
+ dyfunc = (dyfuncptr)__CFLookupCoreServicesInternalFunction(#N); \
+ } \
+ if (dyfunc) { \
+ return dyfunc A ; \
+ } \
+ return __VA_ARGS__ ; \
+ }
+
+#else
#define DEFINE_WEAK_CORESERVICESINTERNAL_FUNC(R, N, P, A, ...)
#endif
return *(CFAllocatorRef *)((char *)cf - sizeof(CFAllocatorRef));
}
-
-#if DEPLOYMENT_TARGET_WINDOWS
-__private_extern__ const wchar_t *_CFDLLPath(void);
-__private_extern__ void __CFStringCleanup(void);
-__private_extern__ void __CFSocketCleanup(void);
-__private_extern__ void __CFUniCharCleanup(void);
-__private_extern__ void __CFStreamCleanup(void);
-#endif
-
/* !!! Avoid #importing objc.h; e.g. converting this to a .m file */
struct __objcFastEnumerationStateEquivalent {
unsigned long state;
unsigned long extra[5];
};
+#pragma mark -
+#pragma mark Windows Compatability
+
+// Need to use the _O_BINARY flag on Windows to get the correct behavior
+#if DEPLOYMENT_TARGET_WINDOWS
+#define CF_OPENFLGS (_O_BINARY|_O_NOINHERIT)
+#else
+#define CF_OPENFLGS (0)
+#endif
+
+#if DEPLOYMENT_TARGET_WINDOWS
+
+// These are replacements for pthread calls on Windows
+CF_EXPORT int _NS_pthread_main_np();
+CF_EXPORT int _NS_pthread_setspecific(pthread_key_t key, const void *val);
+CF_EXPORT void* _NS_pthread_getspecific(pthread_key_t key);
+CF_EXPORT int _NS_pthread_key_init_np(int key, void (*destructor)(void *));
+CF_EXPORT void _NS_pthread_setname_np(const char *name);
+
+// map use of pthread_set/getspecific to internal API
+#define pthread_setspecific _NS_pthread_setspecific
+#define pthread_getspecific _NS_pthread_getspecific
+#define pthread_key_init_np _NS_pthread_key_init_np
+#define pthread_main_np _NS_pthread_main_np
+#define pthread_setname_np _NS_pthread_setname_np
+#endif
+
+#if DEPLOYMENT_TARGET_WINDOWS
+// replacement for DISPATCH_QUEUE_OVERCOMMIT until we get a bug fix in dispatch on Windows
+// <rdar://problem/7923891> dispatch on Windows: Need queue_private.h
+#define DISPATCH_QUEUE_OVERCOMMIT 2
+#endif
+
+#if DEPLOYMENT_TARGET_WINDOWS
+__private_extern__ const wchar_t *_CFDLLPath(void);
+#endif
+
+/* Buffer size for file pathname */
+#if DEPLOYMENT_TARGET_WINDOWS
+#define CFMaxPathSize ((CFIndex)262)
+#define CFMaxPathLength ((CFIndex)260)
+#define PATH_SEP '\\'
+#define PATH_SEP_STR CFSTR("\\")
+#define PATH_MAX MAX_PATH
+#else
+#define CFMaxPathSize ((CFIndex)1026)
+#define CFMaxPathLength ((CFIndex)1024)
+#define PATH_SEP '/'
+#define PATH_SEP_STR CFSTR("/")
+#endif
+
CF_EXTERN_C_END
#endif /* ! __COREFOUNDATION_CFINTERNAL__ */
*/
/* CFLocale.c
- Copyright (c) 2002-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2002-2012, Apple Inc. All rights reserved.
Responsibility: David Smith
*/
#include <CoreFoundation/CFNumber.h>
#include "CFInternal.h"
#include "CFLocaleInternal.h"
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
#include <unicode/uloc.h> // ICU locales
#include <unicode/ulocdata.h> // ICU locale data
#include <unicode/ucal.h>
#include <unicode/uset.h> // ICU Unicode sets
#include <unicode/putil.h> // ICU low-level utilities
#include <unicode/umsg.h> // ICU message formatting
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#include <unicode/ucol.h>
+#endif
#include <CoreFoundation/CFNumberFormatter.h>
#include <stdlib.h>
#include <stdio.h>
-#include <unicode/ucol.h>
-#elif DEPLOYMENT_TARGET_WINDOWS
-#include <stdio.h>
-#endif
#include <string.h>
+#if DEPLOYMENT_TARGET_EMBEDDED_MINI
+// Some compatability definitions
+#define ULOC_FULLNAME_CAPACITY 157
+#define ULOC_KEYWORD_AND_VALUES_CAPACITY 100
+
+//typedef long UErrorCode;
+//#define U_BUFFER_OVERFLOW_ERROR 15
+//#define U_ZERO_ERROR 0
+//
+//typedef uint16_t UChar;
+#endif
+
+
CONST_STRING_DECL(kCFLocaleCurrentLocaleDidChangeNotification, "kCFLocaleCurrentLocaleDidChangeNotification")
static const char *kCalendarKeyword = "calendar";
#if DEPLOYMENT_TARGET_MACOSX
#define FALLBACK_LOCALE_NAME CFSTR("")
-#elif DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#define FALLBACK_LOCALE_NAME CFSTR("en_US")
#elif DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
#define FALLBACK_LOCALE_NAME CFSTR("en_US")
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
CFLocaleRef CFLocaleCopyCurrent(void) {
+ CFStringRef name = NULL, 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 0 // DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
+ name = (CFStringRef)CFPreferencesCopyAppValue(CFSTR("AppleLocale"), kCFPreferencesCurrentApplication);
+#endif
+ if (name && (CFStringGetTypeID() == CFGetTypeID(name))) {
+ ident = CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault, name);
+ }
+ if (name) CFRelease(name);
+ CFLocaleRef oldLocale = NULL;
__CFLocaleLockGlobal();
if (__CFLocaleCurrent) {
- CFRetain(__CFLocaleCurrent);
- __CFLocaleUnlockGlobal();
- return __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);
+ 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;
}
__private_extern__ CFDictionaryRef __CFLocaleGetPrefs(CFLocaleRef locale) {
- CF_OBJC_FUNCDISPATCH0(CFLocaleGetTypeID(), CFDictionaryRef, locale, "_prefs");
+ CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFDictionaryRef, (NSLocale *)locale, _prefs);
return locale->_prefs;
}
}
CFStringRef CFLocaleGetIdentifier(CFLocaleRef locale) {
- CF_OBJC_FUNCDISPATCH0(CFLocaleGetTypeID(), CFStringRef, locale, "localeIdentifier");
+ CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFStringRef, (NSLocale *)locale, localeIdentifier);
return locale->_identifier;
}
}
}
#endif
- CF_OBJC_FUNCDISPATCH1(CFLocaleGetTypeID(), CFTypeRef, locale, "objectForKey:", key);
+ CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFTypeRef, (NSLocale *)locale, objectForKey:(id)key);
CFIndex idx, slot = -1;
for (idx = 0; idx < __kCFLocaleKeyTableCount; idx++) {
if (__CFLocaleKeyTable[idx].key == key) {
}
CFStringRef CFLocaleCopyDisplayNameForPropertyValue(CFLocaleRef displayLocale, CFStringRef key, CFStringRef value) {
- CF_OBJC_FUNCDISPATCH2(CFLocaleGetTypeID(), CFStringRef, displayLocale, "_copyDisplayNameForKey:value:", key, value);
+ CF_OBJC_FUNCDISPATCHV(CFLocaleGetTypeID(), CFStringRef, (NSLocale *)displayLocale, _copyDisplayNameForKey:(id)key value:(id)value);
CFIndex idx, slot = -1;
for (idx = 0; idx < __kCFLocaleKeyTableCount; idx++) {
if (__CFLocaleKeyTable[idx].key == key) {
}
// We could not find a result using the requested language. Fall back through all preferred languages.
- CFArrayRef langPref;
+ CFArrayRef langPref = NULL;
if (displayLocale->_prefs) {
langPref = (CFArrayRef)CFDictionaryGetValue(displayLocale->_prefs, CFSTR("AppleLanguages"));
if (langPref) CFRetain(langPref);
} else {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
langPref = (CFArrayRef)CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), kCFPreferencesCurrentApplication);
+#endif
}
if (langPref != NULL) {
CFIndex count = CFArrayGetCount(langPref);
}
CFArrayRef CFLocaleCopyAvailableLocaleIdentifiers(void) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
int32_t locale, localeCount = uloc_countAvailable();
CFMutableSetRef working = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
for (locale = 0; locale < localeCount; ++locale) {
CFArrayRef result = CFArrayCreate(kCFAllocatorSystemDefault, buffer, cnt, &kCFTypeArrayCallBacks);
CFRelease(working);
return result;
+#else
+ return CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks);
+#endif
}
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
static CFArrayRef __CFLocaleCopyCStringsAsArray(const char* const* p) {
CFMutableArrayRef working = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
for (; *p; ++p) {
}
return result;
}
+#endif
CFArrayRef CFLocaleCopyISOLanguageCodes(void) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
const char* const* p = uloc_getISOLanguages();
return __CFLocaleCopyCStringsAsArray(p);
+#else
+ return CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks);
+#endif
}
CFArrayRef CFLocaleCopyISOCountryCodes(void) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
const char* const* p = uloc_getISOCountries();
return __CFLocaleCopyCStringsAsArray(p);
+#else
+ return CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks);
+#endif
}
CFArrayRef CFLocaleCopyISOCurrencyCodes(void) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
UErrorCode icuStatus = U_ZERO_ERROR;
UEnumeration *enumer = ucurr_openISOCurrencies(UCURR_ALL, &icuStatus);
CFArrayRef result = __CFLocaleCopyUEnumerationAsArray(enumer, &icuStatus);
uenum_close(enumer);
+#else
+ CFArrayRef result = CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks);
+#endif
return result;
}
CFArrayRef CFLocaleCopyCommonISOCurrencyCodes(void) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
UErrorCode icuStatus = U_ZERO_ERROR;
UEnumeration *enumer = ucurr_openISOCurrencies(UCURR_COMMON|UCURR_NON_DEPRECATED, &icuStatus);
CFArrayRef result = __CFLocaleCopyUEnumerationAsArray(enumer, &icuStatus);
uenum_close(enumer);
+#else
+ CFArrayRef result = CFArrayCreate(kCFAllocatorSystemDefault, NULL, 0, &kCFTypeArrayCallBacks);
+#endif
return result;
}
CFStringRef CFLocaleCreateLocaleIdentifierFromWindowsLocaleCode(CFAllocatorRef allocator, uint32_t lcid) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
char buffer[kMaxICUNameSize];
UErrorCode status = U_ZERO_ERROR;
int32_t ret = uloc_getLocaleForLCID(lcid, buffer, kMaxICUNameSize, &status);
CFStringRef ident = CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault, str);
CFRelease(str);
return ident;
+#else
+ return CFSTR("");
+#endif
}
uint32_t CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier(CFStringRef localeIdentifier) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
CFStringRef ident = CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault, localeIdentifier);
char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
- Boolean b = CFStringGetCString(ident, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII);
- CFRelease(ident);
+ Boolean b = ident ? CFStringGetCString(ident, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII) : false;
+ if (ident) CFRelease(ident);
return b ? uloc_getLCID(localeID) : 0;
+#else
+ return 0;
+#endif
}
CFLocaleLanguageDirection CFLocaleGetLanguageCharacterDirection(CFStringRef isoLangCode) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
- Boolean b = CFStringGetCString(isoLangCode, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII);
+ Boolean b = isoLangCode ? CFStringGetCString(isoLangCode, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII) : false;
CFLocaleLanguageDirection dir;
UErrorCode status = U_ZERO_ERROR;
ULayoutType idir = b ? uloc_getCharacterOrientation(localeID, &status) : ULOC_LAYOUT_UNKNOWN;
default: dir = kCFLocaleLanguageDirectionUnknown; break;
}
return dir;
+#else
+ return kCFLocaleLanguageDirectionLeftToRight;
+#endif
}
CFLocaleLanguageDirection CFLocaleGetLanguageLineDirection(CFStringRef isoLangCode) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
- Boolean b = CFStringGetCString(isoLangCode, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII);
+ Boolean b = isoLangCode ? CFStringGetCString(isoLangCode, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII) : false;
CFLocaleLanguageDirection dir;
UErrorCode status = U_ZERO_ERROR;
ULayoutType idir = b ? uloc_getLineOrientation(localeID, &status) : ULOC_LAYOUT_UNKNOWN;
default: dir = kCFLocaleLanguageDirectionUnknown; break;
}
return dir;
+#else
+ return kCFLocaleLanguageDirectionLeftToRight;
+#endif
}
CFArrayRef CFLocaleCopyPreferredLanguages(void) {
CFMutableArrayRef newArray = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
CFArrayRef languagesArray = (CFArrayRef)CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), kCFPreferencesCurrentApplication);
if (languagesArray && (CFArrayGetTypeID() == CFGetTypeID(languagesArray))) {
for (CFIndex idx = 0, cnt = CFArrayGetCount(languagesArray); idx < cnt; idx++) {
}
}
if (languagesArray) CFRelease(languagesArray);
+#endif
return newArray;
}
return false;
}
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
CFCharacterSetRef _CFCreateCharacterSetFromUSet(USet *set) {
UErrorCode icuErr = U_ZERO_ERROR;
CFMutableCharacterSetRef working = CFCharacterSetCreateMutable(NULL);
CFRelease(working);
return result;
}
-
+#endif
static bool __CFLocaleCopyExemplarCharSet(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
if (CFStringGetCString(locale->_identifier, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII)) {
UErrorCode icuStatus = U_ZERO_ERROR;
uset_close(set);
return (*cf != NULL);
}
+#endif
return false;
}
static bool __CFLocaleCopyICUKeyword(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context, const char *keyword)
{
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
if (CFStringGetCString(locale->_identifier, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII))
{
return true;
}
}
+#endif
*cf = NULL;
return false;
}
static bool __CFLocaleCopyICUCalendarID(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context, const char *keyword) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
char localeID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
if (CFStringGetCString(locale->_identifier, localeID, sizeof(localeID)/sizeof(char), kCFStringEncodingASCII)) {
UErrorCode icuStatus = U_ZERO_ERROR;
}
uenum_close(en);
}
+#endif
*cf = NULL;
return false;
}
}
static bool __CFLocaleCopyCalendar(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (__CFLocaleCopyCalendarID(locale, user, cf, context)) {
CFCalendarRef calendar = CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault, (CFStringRef)*cf);
CFCalendarSetLocale(calendar, locale);
*cf = calendar;
return true;
}
+#endif
return false;
}
static bool __CFLocaleCopyDelimiter(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
ULocaleDataDelimiterType type = (ULocaleDataDelimiterType)0;
if (context == kCFLocaleQuotationBeginDelimiterKey) {
type = ULOCDATA_QUOTATION_START;
*cf = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (UniChar *)buffer, len);
return (*cf != NULL);
+#else
+ if (context == kCFLocaleQuotationBeginDelimiterKey || context == kCFLocaleQuotationEndDelimiterKey || context == kCFLocaleAlternateQuotationBeginDelimiterKey || context == kCFLocaleAlternateQuotationEndDelimiterKey) {
+ *cf = CFRetain(CFSTR("\""));
+ return true;
+ } else {
+ return false;
+ }
+#endif
}
static bool __CFLocaleCopyCollationID(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
static bool __CFLocaleCopyCollatorID(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
CFStringRef canonLocaleCFStr = NULL;
- if (user) {
+ if (user && locale->_prefs) {
CFStringRef pref = (CFStringRef)CFDictionaryGetValue(locale->_prefs, CFSTR("AppleCollationOrder"));
if (pref) {
// Canonicalize pref string in case it's not in the canonical format.
}
static bool __CFLocaleCopyUsesMetric(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
bool us = false; // Default is Metric
bool done = false;
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
us = false;
*cf = us ? CFRetain(kCFBooleanFalse) : CFRetain(kCFBooleanTrue);
return true;
+#else
+ *cf = CFRetain(kCFBooleanFalse);
+ return true;
+#endif
}
static bool __CFLocaleCopyMeasurementSystem(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
static bool __CFLocaleCopyNumberFormat(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
CFStringRef str = NULL;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorSystemDefault, locale, kCFNumberFormatterDecimalStyle);
- str = nf ? CFNumberFormatterCopyProperty(nf, context) : NULL;
+ str = nf ? (CFStringRef)CFNumberFormatterCopyProperty(nf, context) : NULL;
if (nf) CFRelease(nf);
-#elif DEPLOYMENT_TARGET_WINDOWS
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
if (str) {
*cf = str;
// so we have to have another routine here which creates a Currency number formatter.
static bool __CFLocaleCopyNumberFormat2(CFLocaleRef locale, bool user, CFTypeRef *cf, CFStringRef context) {
CFStringRef str = NULL;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorSystemDefault, locale, kCFNumberFormatterCurrencyStyle);
- str = nf ? CFNumberFormatterCopyProperty(nf, context) : NULL;
+ str = nf ? (CFStringRef)CFNumberFormatterCopyProperty(nf, context) : NULL;
if (nf) CFRelease(nf);
-#elif DEPLOYMENT_TARGET_WINDOWS
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
if (str) {
*cf = str;
return false;
}
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
typedef int32_t (*__CFICUFunction)(const char *, const char *, UChar *, int32_t, UErrorCode *);
static bool __CFLocaleICUName(const char *locale, const char *valLocale, CFStringRef *out, __CFICUFunction icu) {
*out = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (UniChar *)name, size);
return (*out != NULL);
}
+#endif
static bool __CFLocaleFullName(const char *locale, const char *value, CFStringRef *out) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
UErrorCode icuStatus = U_ZERO_ERROR;
int32_t size;
UChar name[kMaxICUNameSize];
// This locale is OK, so use the result.
*out = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (UniChar *)name, size);
return (*out != NULL);
+#else
+ *out = CFRetain(CFSTR("(none)"));
+ return true;
+#endif
}
static bool __CFLocaleLanguageName(const char *locale, const char *value, CFStringRef *out) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
return __CFLocaleICUName(locale, value, out, uloc_getDisplayLanguage);
+#else
+ *out = CFRetain(CFSTR("(none)"));
+ return true;
+#endif
}
static bool __CFLocaleCountryName(const char *locale, const char *value, CFStringRef *out) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
// Need to make a fake locale ID
char lid[ULOC_FULLNAME_CAPACITY];
if (strlen(value) < sizeof(lid) - 3) {
return __CFLocaleICUName(locale, lid, out, uloc_getDisplayCountry);
}
return false;
+#else
+ *out = CFRetain(CFSTR("(none)"));
+ return true;
+#endif
}
static bool __CFLocaleScriptName(const char *locale, const char *value, CFStringRef *out) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
// Need to make a fake locale ID
char lid[ULOC_FULLNAME_CAPACITY];
if (strlen(value) == 4) {
return __CFLocaleICUName(locale, lid, out, uloc_getDisplayScript);
}
return false;
+#else
+ *out = CFRetain(CFSTR("(none)"));
+ return true;
+#endif
}
static bool __CFLocaleVariantName(const char *locale, const char *value, CFStringRef *out) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
// Need to make a fake locale ID
char lid[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
if (strlen(value) < sizeof(lid) - 6) {
return __CFLocaleICUName(locale, lid, out, uloc_getDisplayVariant);
}
return false;
+#else
+ *out = CFRetain(CFSTR("(none)"));
+ return true;
+#endif
}
static bool __CFLocaleCalendarName(const char *locale, const char *value, CFStringRef *out) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
return __CFLocaleICUKeywordValueName(locale, value, kCalendarKeyword, out);
+#else
+ *out = CFRetain(CFSTR("(none)"));
+ return true;
+#endif
}
static bool __CFLocaleCollationName(const char *locale, const char *value, CFStringRef *out) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
return __CFLocaleICUKeywordValueName(locale, value, kCollationKeyword, out);
+#else
+ *out = CFRetain(CFSTR("(none)"));
+ return true;
+#endif
}
static bool __CFLocaleCurrencyShortName(const char *locale, const char *value, CFStringRef *out) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
return __CFLocaleICUCurrencyName(locale, value, UCURR_SYMBOL_NAME, out);
+#else
+ *out = CFRetain(CFSTR("(none)"));
+ return true;
+#endif
}
static bool __CFLocaleCurrencyFullName(const char *locale, const char *value, CFStringRef *out) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
return __CFLocaleICUCurrencyName(locale, value, UCURR_LONG_NAME, out);
+#else
+ *out = CFRetain(CFSTR("(none)"));
+ return true;
+#endif
}
static bool __CFLocaleNoName(const char *locale, const char *value, CFStringRef *out) {
*/
/* CFLocale.h
- Copyright (c) 2002-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2002-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFLOCALE__)
#include <CoreFoundation/CFArray.h>
#include <CoreFoundation/CFDictionary.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
typedef const struct __CFLocale *CFLocaleRef;
uint32_t CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier(CFStringRef localeIdentifier) CF_AVAILABLE(10_6, 4_0);
// Map a locale identifier to a Windows LCID.
-enum {
+typedef CF_ENUM(CFIndex, CFLocaleLanguageDirection) {
kCFLocaleLanguageDirectionUnknown = 0,
kCFLocaleLanguageDirectionLeftToRight = 1,
kCFLocaleLanguageDirectionRightToLeft = 2,
kCFLocaleLanguageDirectionTopToBottom = 3,
kCFLocaleLanguageDirectionBottomToTop = 4
};
-typedef CFIndex CFLocaleLanguageDirection;
CF_EXPORT
CFLocaleLanguageDirection CFLocaleGetLanguageCharacterDirection(CFStringRef isoLangCode) CF_AVAILABLE(10_6, 4_0);
CF_EXPORT const CFStringRef kCFISO8601Calendar CF_AVAILABLE(10_6, 4_0);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFLOCALE__ */
/*
CFLocaleIdentifier.c
- Copyright (c) 2002-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2002-2012, Apple Inc. All rights reserved.
Responsibility: David Smith
CFLocaleIdentifier.c defines
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
#include <unicode/uloc.h>
+#else
+#define ULOC_KEYWORD_SEPARATOR '@'
+#define ULOC_FULLNAME_CAPACITY 56
+#define ULOC_KEYWORD_AND_VALUES_CAPACITY 100
+#endif
#include "CFInternal.h"
#include "CFLocaleInternal.h"
// If so, copy the keywords to varKeyValueString and delete the variant tag
// from the original string (but don't otherwise use the ICU canonicalization).
varKeyValueString[0] = 0;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (variantTag) {
UErrorCode icuStatus;
int icuCanonStringLen;
*varKeyValueStringPtr = 0;
}
}
+#endif
// 4. Handle special cases of updating region codes, or updating language codes based on
// region code.
}
static void _AppendKeyValueString(char inLocaleString[], int locStringMaxLen, char keyValueString[]) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (keyValueString[0] != 0) {
UErrorCode uerr = U_ZERO_ERROR;
UEnumeration * uenum = uloc_openKeywords(keyValueString, &uerr);
uenum_close(uenum);
}
}
+#endif
}
// __private_extern__ CFStringRef _CFLocaleCreateCanonicalLanguageIdentifierForCFBundle(CFAllocatorRef allocator, CFStringRef localeIdentifier) {}
preferred localization in the current context (this function returns NO for a NULL localeIdentifier); and in this function
langCode, regCode, and scriptCode are all SInt16* (not SInt32* like the equivalent parameters in CFBundleGetLocalizationInfoForLocalization).
*/
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
static int CompareLocaleToLegacyCodesEntries( const void *entry1, const void *entry2 );
+#endif
Boolean CFLocaleGetLanguageRegionEncodingForLocaleIdentifier(CFStringRef localeIdentifier, LangCode *langCode, RegionCode *regCode, ScriptCode *scriptCode, CFStringEncoding *stringEncoding) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
Boolean returnValue = false;
CFStringRef canonicalIdentifier = CFLocaleCreateCanonicalLocaleIdentifierFromString(NULL, localeIdentifier);
if (canonicalIdentifier) {
CFRelease(canonicalIdentifier);
}
return returnValue;
+#else
+ return false;
+#endif
}
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
static int CompareLocaleToLegacyCodesEntries( const void *entry1, const void *entry2 ) {
const char * localeString1 = ((const LocaleToLegacyCodes *)entry1)->locale;
const char * localeString2 = ((const LocaleToLegacyCodes *)entry2)->locale;
return strcmp(localeString1, localeString2);
}
-
+#endif
CFDictionaryRef CFLocaleCreateComponentsFromLocaleIdentifier(CFAllocatorRef allocator, CFStringRef localeID) {
+ CFMutableDictionaryRef working = CFDictionaryCreateMutable(allocator, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
char cLocaleID[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
char buffer[ULOC_FULLNAME_CAPACITY+ULOC_KEYWORD_AND_VALUES_CAPACITY];
- CFMutableDictionaryRef working = CFDictionaryCreateMutable(allocator, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
UErrorCode icuStatus = U_ZERO_ERROR;
int32_t length = 0;
-
+
+ if (!localeID) goto out;
+
// Extract the C string locale ID, for ICU
CFIndex outBytes = 0;
CFStringGetBytes(localeID, CFRangeMake(0, CFStringGetLength(localeID)), kCFStringEncodingASCII, (UInt8) '?', true, (unsigned char *)cLocaleID, sizeof(cLocaleID)/sizeof(char) - 1, &outBytes);
}
uenum_close(iter);
+ out:;
+#endif
// Convert to an immutable dictionary and return
CFDictionaryRef result = CFDictionaryCreateCopy(allocator, working);
CFRelease(working);
}
CFStringRef CFLocaleCreateLocaleIdentifierFromComponents(CFAllocatorRef allocator, CFDictionaryRef dictionary) {
+ if (!dictionary) return NULL;
+
CFIndex cnt = CFDictionaryGetCount(dictionary);
STACK_BUFFER_DECL(CFStringRef, values, cnt);
STACK_BUFFER_DECL(CFStringRef, keys, cnt);
free(variant);
free(buf1);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
for (CFIndex idx = 0; idx < cnt; idx++) {
if (keys[idx]) {
char *key = __CStringFromString(keys[idx]);
free(value);
}
}
-
+#endif
+
return CFStringCreateWithCString(allocator, cLocaleID, kCFStringEncodingASCII);
}
/*
CFLocaleInternal.h
- Copyright (c) 2008-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2008-2012, Apple Inc. All rights reserved.
*/
/*
CF_EXPORT CFStringRef const kCFDateFormatterLongEraSymbolsKey;
CF_EXPORT CFStringRef const kCFDateFormatterMonthSymbolsKey;
CF_EXPORT CFStringRef const kCFDateFormatterPMSymbolKey;
+CF_EXPORT CFStringRef const kCFDateFormatterAmbiguousYearStrategyKey;
CF_EXPORT CFStringRef const kCFDateFormatterQuarterSymbolsKey;
CF_EXPORT CFStringRef const kCFDateFormatterShortMonthSymbolsKey;
CF_EXPORT CFStringRef const kCFDateFormatterShortQuarterSymbolsKey;
*/
/* CFLocaleKeys.c
- Copyright (c) 2008-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2008-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
-#include <CoreFoundation/CFInternal.h>
+#include "CFInternal.h"
CONST_STRING_DECL(kCFLocaleAlternateQuotationBeginDelimiterKey, "kCFLocaleAlternateQuotationBeginDelimiterKey");
CONST_STRING_DECL(kCFLocaleAlternateQuotationEndDelimiterKey, "kCFLocaleAlternateQuotationEndDelimiterKey");
CONST_STRING_DECL(kCFDateFormatterLongEraSymbolsKey, "kCFDateFormatterLongEraSymbolsKey");
CONST_STRING_DECL(kCFDateFormatterMonthSymbolsKey, "kCFDateFormatterMonthSymbolsKey");
CONST_STRING_DECL(kCFDateFormatterPMSymbolKey, "kCFDateFormatterPMSymbolKey");
+CONST_STRING_DECL(kCFDateFormatterAmbiguousYearStrategyKey, "kCFDateFormatterAmbiguousYearStrategyKey");
CONST_STRING_DECL(kCFDateFormatterQuarterSymbolsKey, "kCFDateFormatterQuarterSymbolsKey");
CONST_STRING_DECL(kCFDateFormatterShortMonthSymbolsKey, "kCFDateFormatterShortMonthSymbolsKey");
CONST_STRING_DECL(kCFDateFormatterShortQuarterSymbolsKey, "kCFDateFormatterShortQuarterSymbolsKey");
*/
/* CFLogUtilities.h
- Copyright (c) 2004-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2004-2012, Apple Inc. All rights reserved.
*/
/*
*/
/* CFMachPort.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
#include <CoreFoundation/CFRunLoop.h>
#include <CoreFoundation/CFArray.h>
#include <dispatch/dispatch.h>
+#include <dispatch/private.h>
#include <mach/mach.h>
#include <dlfcn.h>
#include "CFInternal.h"
-#define AVOID_WEAK_COLLECTIONS 1
-#if DEPLOYMENT_TARGET_EMBEDDED
#define AVOID_WEAK_COLLECTIONS 1
-#endif
-#if !defined(AVOID_WEAK_COLLECTIONS)
+#if !AVOID_WEAK_COLLECTIONS
#import "CFPointerArray.h"
#endif
-DISPATCH_HELPER_FUNCTIONS(port, CFMachPort)
+static dispatch_queue_t _CFMachPortQueue() {
+ static volatile dispatch_queue_t __CFMachPortQueue = NULL;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{ __CFMachPortQueue = dispatch_queue_create("CFMachPort Queue", NULL); });
+ return __CFMachPortQueue;
+}
enum {
struct __CFMachPort {
CFRuntimeBase _base;
int32_t _state;
- mach_port_t _port; /* immutable */
- dispatch_source_t _dsrc;
- dispatch_source_t _dsrc2;
- dispatch_semaphore_t _dsrc_sem;
- dispatch_semaphore_t _dsrc2_sem;
- CFMachPortInvalidationCallBack _icallout;
- CFRunLoopSourceRef _source; /* immutable, once created */
- CFMachPortCallBack _callout; /* immutable */
- CFMachPortContext _context; /* immutable */
+ 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;
};
/* Bit 1 in the base reserved bits is used for has-receive-ref state */
return result;
}
+// Only call with mp->_lock locked
+CF_INLINE void __CFMachPortInvalidateLocked(CFRunLoopSourceRef source, CFMachPortRef mp) {
+ CFMachPortInvalidationCallBack cb = mp->_icallout;
+ if (cb) {
+ __CFSpinUnlock(&mp->_lock);
+ cb(mp, mp->_context.info);
+ __CFSpinLock(&mp->_lock);
+ }
+ if (NULL != source) {
+ __CFSpinUnlock(&mp->_lock);
+ CFRunLoopSourceInvalidate(source);
+ CFRelease(source);
+ __CFSpinLock(&mp->_lock);
+ }
+ void *info = mp->_context.info;
+ mp->_context.info = NULL;
+ if (mp->_context.release) {
+ __CFSpinUnlock(&mp->_lock);
+ mp->_context.release(info);
+ __CFSpinLock(&mp->_lock);
+ }
+ mp->_state = kCFMachPortStateInvalid;
+ OSMemoryBarrier();
+}
+
static void __CFMachPortDeallocate(CFTypeRef cf) {
CHECK_FOR_FORK_RET();
CFMachPortRef mp = (CFMachPortRef)cf;
// CFMachPortRef is invalid before we get here, except under GC
- __block CFRunLoopSourceRef source = NULL;
- __block Boolean wasReady = false;
- void (^block)(void) = ^{
- wasReady = (mp->_state == kCFMachPortStateReady);
- if (wasReady) {
- mp->_state = kCFMachPortStateInvalidating;
- OSMemoryBarrier();
- if (mp->_dsrc) {
- 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;
- }
- };
- if (!__portSyncDispatchIsSafe(__portQueue())) {
- block();
- } else {
- dispatch_sync(__portQueue(), block);
- }
+ __CFSpinLock(&mp->_lock);
+ CFRunLoopSourceRef source = NULL;
+ Boolean wasReady = (mp->_state == kCFMachPortStateReady);
if (wasReady) {
- CFMachPortInvalidationCallBack cb = mp->_icallout;
- if (cb) {
- cb(mp, mp->_context.info);
- }
- if (NULL != source) {
- CFRunLoopSourceInvalidate(source);
- CFRelease(source);
+ mp->_state = kCFMachPortStateInvalidating;
+ OSMemoryBarrier();
+ if (mp->_dsrc) {
+ dispatch_source_cancel(mp->_dsrc);
+ mp->_dsrc = NULL;
}
- void *info = mp->_context.info;
- mp->_context.info = NULL;
- if (mp->_context.release) {
- mp->_context.release(info);
+ if (mp->_dsrc2) {
+ dispatch_source_cancel(mp->_dsrc2);
+ mp->_dsrc2 = NULL;
}
- mp->_state = kCFMachPortStateInvalid;
- OSMemoryBarrier();
+ source = mp->_source;
+ mp->_source = NULL;
+ }
+ if (wasReady) {
+ __CFMachPortInvalidateLocked(source, mp);
}
mp->_state = kCFMachPortStateDeallocating;
dispatch_semaphore_t sem2 = mp->_dsrc2_sem;
Boolean doSend2 = __CFMachPortHasSend2(mp), doSend = __CFMachPortHasSend(mp), doReceive = __CFMachPortHasReceive(mp);
+ __CFSpinUnlock(&mp->_lock);
+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
if (sem1) {
dispatch_semaphore_wait(sem1, DISPATCH_TIME_FOREVER);
});
}
-#if defined(AVOID_WEAK_COLLECTIONS)
+// This lock protects __CFAllMachPorts. Take before any instance-specific lock.
+static CFSpinLock_t __CFAllMachPortsLock = CFSpinLockInit;
+
+#if AVOID_WEAK_COLLECTIONS
static CFMutableArrayRef __CFAllMachPorts = NULL;
#else
static __CFPointerArray *__CFAllMachPorts = nil;
return (KERN_SUCCESS != ret || (0 == (type & MACH_PORT_TYPE_PORT_RIGHTS))) ? false : true;
}
-static void __CFMachPortChecker(Boolean fromTimer) { // only call on __portQueue()
-#if defined(AVOID_WEAK_COLLECTIONS)
+static void __CFMachPortChecker(Boolean fromTimer) {
+ __CFSpinLock(&__CFAllMachPortsLock); // take this lock first before any instance-specific lock
+#if AVOID_WEAK_COLLECTIONS
for (CFIndex idx = 0, cnt = __CFAllMachPorts ? CFArrayGetCount(__CFAllMachPorts) : 0; idx < cnt; idx++) {
CFMachPortRef mp = (CFMachPortRef)CFArrayGetValueAtIndex(__CFAllMachPorts, idx);
#else
CFRunLoopSourceRef source = NULL;
Boolean wasReady = (mp->_state == kCFMachPortStateReady);
if (wasReady) {
+ __CFSpinLock(&mp->_lock); // take this lock second
mp->_state = kCFMachPortStateInvalidating;
OSMemoryBarrier();
if (mp->_dsrc) {
source = mp->_source;
mp->_source = NULL;
CFRetain(mp);
+ __CFSpinUnlock(&mp->_lock);
dispatch_async(dispatch_get_main_queue(), ^{
- CFMachPortInvalidationCallBack cb = mp->_icallout;
- if (cb) {
- cb(mp, mp->_context.info);
- }
- if (NULL != source) {
- CFRunLoopSourceInvalidate(source);
- CFRelease(source);
- }
- void *info = mp->_context.info;
- mp->_context.info = NULL;
- if (mp->_context.release) {
- mp->_context.release(info);
- }
- // For hashing and equality purposes, cannot get rid of _port here
- mp->_state = kCFMachPortStateInvalid;
- OSMemoryBarrier();
- CFRelease(mp);
- });
+ // We can grab the mach port-specific spin lock here since we're no longer on the same thread as the one taking the all mach ports spin lock.
+ // But be sure to release it during callouts
+ __CFSpinLock(&mp->_lock);
+ __CFMachPortInvalidateLocked(source, mp);
+ __CFSpinUnlock(&mp->_lock);
+ CFRelease(mp);
+ });
}
-#if defined(AVOID_WEAK_COLLECTIONS)
+#if AVOID_WEAK_COLLECTIONS
CFArrayRemoveValueAtIndex(__CFAllMachPorts, idx);
#else
[__CFAllMachPorts removePointerAtIndex:idx];
cnt--;
}
}
-#if !defined(AVOID_WEAK_COLLECTIONS)
+#if !AVOID_WEAK_COLLECTIONS
[__CFAllMachPorts compact];
#endif
+ __CFSpinUnlock(&__CFAllMachPortsLock);
};
return NULL;
}
- __block CFMachPortRef mp = NULL;
- dispatch_sync(__portQueue(), ^{
- static dispatch_source_t timerSource = NULL;
- if (timerSource == NULL) {
- uint64_t nanos = 63 * 1000 * 1000 * 1000ULL;
- uint64_t leeway = 9 * 1000ULL;
- timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, __portQueue());
- dispatch_source_set_timer(timerSource, dispatch_time(DISPATCH_TIME_NOW, nanos), nanos, leeway);
- dispatch_source_set_event_handler(timerSource, ^{
- __CFMachPortChecker(true);
- });
- dispatch_resume(timerSource);
- }
+ 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);
+ dispatch_source_set_event_handler(timerSource, ^{
+ __CFMachPortChecker(true);
+ });
+ dispatch_resume(timerSource);
+ });
-#if defined(AVOID_WEAK_COLLECTIONS)
- for (CFIndex idx = 0, cnt = __CFAllMachPorts ? CFArrayGetCount(__CFAllMachPorts) : 0; idx < cnt; idx++) {
- CFMachPortRef p = (CFMachPortRef)CFArrayGetValueAtIndex(__CFAllMachPorts, idx);
- if (p && p->_port == port) {
- CFRetain(p);
- mp = p;
- return;
- }
- }
+ CFMachPortRef mp = NULL;
+ __CFSpinLock(&__CFAllMachPortsLock);
+#if AVOID_WEAK_COLLECTIONS
+ for (CFIndex idx = 0, cnt = __CFAllMachPorts ? CFArrayGetCount(__CFAllMachPorts) : 0; idx < cnt; idx++) {
+ CFMachPortRef p = (CFMachPortRef)CFArrayGetValueAtIndex(__CFAllMachPorts, idx);
+ if (p && p->_port == port) {
+ CFRetain(p);
+ mp = p;
+ break;
+ }
+ }
#else
- for (CFIndex idx = 0, cnt = __CFAllMachPorts ? [__CFAllMachPorts count] : 0; idx < cnt; idx++) {
- CFMachPortRef p = (CFMachPortRef)[__CFAllMachPorts pointerAtIndex:idx];
- if (p && p->_port == port) {
- CFRetain(p);
- mp = p;
- return;
- }
- }
-#endif
-
- CFIndex size = sizeof(struct __CFMachPort) - sizeof(CFRuntimeBase);
- CFMachPortRef memory = (CFMachPortRef)_CFRuntimeCreateInstance(allocator, CFMachPortGetTypeID(), size, NULL);
- if (NULL == memory) {
- return;
- }
- 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->_callout = callout;
- if (NULL != context) {
- objc_memmove_collectable(&memory->_context, context, sizeof(CFMachPortContext));
- memory->_context.info = context->retain ? (void *)context->retain(context->info) : context->info;
- }
- memory->_state = kCFMachPortStateReady;
-#if defined(AVOID_WEAK_COLLECTIONS)
- if (!__CFAllMachPorts) __CFAllMachPorts = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
- CFArrayAppendValue(__CFAllMachPorts, memory);
-#else
- if (!__CFAllMachPorts) __CFAllMachPorts = [[__CFPointerArray alloc] initWithOptions:(kCFUseCollectableAllocator ? CFPointerFunctionsZeroingWeakMemory : CFPointerFunctionsStrongMemory)];
- [__CFAllMachPorts addPointer:memory];
+ for (CFIndex idx = 0, cnt = __CFAllMachPorts ? [__CFAllMachPorts count] : 0; idx < cnt; idx++) {
+ CFMachPortRef p = (CFMachPortRef)[__CFAllMachPorts pointerAtIndex:idx];
+ if (p && p->_port == port) {
+ CFRetain(p);
+ mp = p;
+ break;
+ }
+ }
#endif
- mp = memory;
- if (shouldFreeInfo) *shouldFreeInfo = false;
-
- if (type & MACH_PORT_TYPE_SEND_RIGHTS) {
- dispatch_source_t theSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_SEND, port, DISPATCH_MACH_SEND_DEAD, __portQueue());
- 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); });
- }
- });
+ __CFSpinUnlock(&__CFAllMachPortsLock);
+
+ if (!mp) {
+ CFIndex size = sizeof(struct __CFMachPort) - sizeof(CFRuntimeBase);
+ CFMachPortRef memory = (CFMachPortRef)_CFRuntimeCreateInstance(allocator, CFMachPortGetTypeID(), size, NULL);
+ if (NULL == memory) {
+ return NULL;
+ }
+ 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->_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->_state = kCFMachPortStateReady;
+ __CFSpinLock(&__CFAllMachPortsLock);
+ #if AVOID_WEAK_COLLECTIONS
+ if (!__CFAllMachPorts) __CFAllMachPorts = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
+ CFArrayAppendValue(__CFAllMachPorts, memory);
+ #else
+ if (!__CFAllMachPorts) __CFAllMachPorts = [[__CFPointerArray alloc] initWithOptions:(kCFUseCollectableAllocator ? CFPointerFunctionsZeroingWeakMemory : CFPointerFunctionsStrongMemory)];
+ [__CFAllMachPorts addPointer:memory];
+ #endif
+ __CFSpinUnlock(&__CFAllMachPortsLock);
+ mp = memory;
+ if (shouldFreeInfo) *shouldFreeInfo = false;
+
+ 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 (mp && !CFMachPortIsValid(mp)) { // must do this outside lock to avoid deadlock
CFRelease(mp);
mp = NULL;
void CFMachPortInvalidate(CFMachPortRef mp) {
CHECK_FOR_FORK_RET();
- CF_OBJC_FUNCDISPATCH0(CFMachPortGetTypeID(), void, mp, "invalidate");
+ CF_OBJC_FUNCDISPATCHV(CFMachPortGetTypeID(), void, (NSMachPort *)mp, invalidate);
__CFGenericValidateType(mp, CFMachPortGetTypeID());
CFRetain(mp);
- __block CFRunLoopSourceRef source = NULL;
- __block Boolean wasReady = false;
- dispatch_sync(__portQueue(), ^{
- wasReady = (mp->_state == kCFMachPortStateReady);
- if (wasReady) {
- mp->_state = kCFMachPortStateInvalidating;
- OSMemoryBarrier();
-#if defined(AVOID_WEAK_COLLECTIONS)
- for (CFIndex idx = 0, cnt = __CFAllMachPorts ? CFArrayGetCount(__CFAllMachPorts) : 0; idx < cnt; idx++) {
- CFMachPortRef p = (CFMachPortRef)CFArrayGetValueAtIndex(__CFAllMachPorts, idx);
- if (p == mp) {
- CFArrayRemoveValueAtIndex(__CFAllMachPorts, idx);
- break;
- }
- }
+ CFRunLoopSourceRef source = NULL;
+ Boolean wasReady = false;
+ __CFSpinLock(&__CFAllMachPortsLock); // take this lock first
+ __CFSpinLock(&mp->_lock);
+ wasReady = (mp->_state == kCFMachPortStateReady);
+ if (wasReady) {
+ mp->_state = kCFMachPortStateInvalidating;
+ OSMemoryBarrier();
+#if AVOID_WEAK_COLLECTIONS
+ for (CFIndex idx = 0, cnt = __CFAllMachPorts ? CFArrayGetCount(__CFAllMachPorts) : 0; idx < cnt; idx++) {
+ CFMachPortRef p = (CFMachPortRef)CFArrayGetValueAtIndex(__CFAllMachPorts, idx);
+ if (p == mp) {
+ CFArrayRemoveValueAtIndex(__CFAllMachPorts, idx);
+ break;
+ }
+ }
#else
- for (CFIndex idx = 0, cnt = __CFAllMachPorts ? [__CFAllMachPorts count] : 0; idx < cnt; idx++) {
- CFMachPortRef p = (CFMachPortRef)[__CFAllMachPorts pointerAtIndex:idx];
- if (p == mp) {
- [__CFAllMachPorts removePointerAtIndex:idx];
- break;
- }
- }
-#endif
- if (mp->_dsrc) {
- 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;
+ for (CFIndex idx = 0, cnt = __CFAllMachPorts ? [__CFAllMachPorts count] : 0; idx < cnt; idx++) {
+ CFMachPortRef p = (CFMachPortRef)[__CFAllMachPorts pointerAtIndex:idx];
+ if (p == mp) {
+ [__CFAllMachPorts removePointerAtIndex:idx];
+ break;
}
- });
- if (wasReady) {
- CFMachPortInvalidationCallBack cb = mp->_icallout;
- if (cb) {
- cb(mp, mp->_context.info);
}
- if (NULL != source) {
- CFRunLoopSourceInvalidate(source);
- CFRelease(source);
+#endif
+ if (mp->_dsrc) {
+ dispatch_source_cancel(mp->_dsrc);
+ mp->_dsrc = NULL;
}
- void *info = mp->_context.info;
- mp->_context.info = NULL;
- if (mp->_context.release) {
- mp->_context.release(info);
+ if (mp->_dsrc2) {
+ dispatch_source_cancel(mp->_dsrc2);
+ mp->_dsrc2 = NULL;
}
- // For hashing and equality purposes, cannot get rid of _port here
- mp->_state = kCFMachPortStateInvalid;
- OSMemoryBarrier();
+ source = mp->_source;
+ mp->_source = NULL;
+ }
+ __CFSpinUnlock(&mp->_lock);
+ __CFSpinUnlock(&__CFAllMachPortsLock); // release this lock last
+ if (wasReady) {
+ __CFSpinLock(&mp->_lock);
+ __CFMachPortInvalidateLocked(source, mp);
+ __CFSpinUnlock(&mp->_lock);
}
CFRelease(mp);
}
mach_port_t CFMachPortGetPort(CFMachPortRef mp) {
CHECK_FOR_FORK_RET(0);
- CF_OBJC_FUNCDISPATCH0(CFMachPortGetTypeID(), mach_port_t, mp, "machPort");
+ CF_OBJC_FUNCDISPATCHV(CFMachPortGetTypeID(), mach_port_t, (NSMachPort *)mp, machPort);
__CFGenericValidateType(mp, CFMachPortGetTypeID());
return mp->_port;
}
}
Boolean CFMachPortIsValid(CFMachPortRef mp) {
- CF_OBJC_FUNCDISPATCH0(CFMachPortGetTypeID(), Boolean, mp, "isValid");
+ CF_OBJC_FUNCDISPATCHV(CFMachPortGetTypeID(), Boolean, (NSMachPort *)mp, isValid);
__CFGenericValidateType(mp, CFMachPortGetTypeID());
if (!__CFMachPortIsValid(mp)) return false;
mach_port_type_t type = 0;
CFMachPortInvalidationCallBack CFMachPortGetInvalidationCallBack(CFMachPortRef mp) {
__CFGenericValidateType(mp, CFMachPortGetTypeID());
- return mp->_icallout;
+ __CFSpinLock(&mp->_lock);
+ CFMachPortInvalidationCallBack cb = mp->_icallout;
+ __CFSpinUnlock(&mp->_lock);
+ return cb;
}
/* After the CFMachPort has started going invalid, or done invalid, you can't change this, and
void CFMachPortSetInvalidationCallBack(CFMachPortRef mp, CFMachPortInvalidationCallBack callout) {
CHECK_FOR_FORK_RET();
__CFGenericValidateType(mp, CFMachPortGetTypeID());
+ __CFSpinLock(&mp->_lock);
if (__CFMachPortIsValid(mp) || !callout) {
mp->_icallout = callout;
} else if (!mp->_icallout && callout) {
+ __CFSpinUnlock(&mp->_lock);
callout(mp, mp->_context.info);
+ __CFSpinLock(&mp->_lock);
} else {
CFLog(kCFLogLevelWarning, CFSTR("CFMachPortSetInvalidationCallBack(): attempt to set invalidation callback (%p) on invalid CFMachPort (%p) thwarted"), callout, mp);
}
+ __CFSpinUnlock(&mp->_lock);
}
/* Returns the number of messages queued for a receive port. */
static void *__CFMachPortPerform(void *msg, CFIndex size, CFAllocatorRef allocator, void *info) {
CHECK_FOR_FORK_RET(NULL);
CFMachPortRef mp = (CFMachPortRef)info;
- __block Boolean isValid = false;
- __block void *context_info = NULL;
- __block void (*context_release)(const void *) = NULL;
- dispatch_sync(__portQueue(), ^{
- isValid = __CFMachPortIsValid(mp);
- if (!isValid) return;
- if (mp->_context.retain) {
- context_info = (void *)mp->_context.retain(mp->_context.info);
- context_release = mp->_context.release;
- } else {
- context_info = mp->_context.info;
- }
- });
+ __CFSpinLock(&mp->_lock);
+ Boolean isValid = __CFMachPortIsValid(mp);
+ 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;
+ } else {
+ context_info = mp->_context.info;
+ }
+ }
+ __CFSpinUnlock(&mp->_lock);
if (!isValid) return NULL;
mp->_callout(mp, msg, size, context_info);
CHECK_FOR_FORK_RET(NULL);
__CFGenericValidateType(mp, CFMachPortGetTypeID());
if (!CFMachPortIsValid(mp)) return NULL;
- __block CFRunLoopSourceRef result = NULL;
- dispatch_sync(__portQueue(), ^{
- if (!__CFMachPortIsValid(mp)) return;
- if (NULL != mp->_source && !CFRunLoopSourceIsValid(mp->_source)) {
- CFRelease(mp->_source);
- mp->_source = NULL;
- }
- if (NULL == mp->_source) {
- CFRunLoopSourceContext1 context;
- context.version = 1;
- context.info = (void *)mp;
- context.retain = (const void *(*)(const void *))CFRetain;
- context.release = (void (*)(const void *))CFRelease;
- context.copyDescription = (CFStringRef (*)(const void *))__CFMachPortCopyDescription;
- context.equal = (Boolean (*)(const void *, const void *))__CFMachPortEqual;
- context.hash = (CFHashCode (*)(const void *))__CFMachPortHash;
- context.getPort = __CFMachPortGetPort;
- context.perform = __CFMachPortPerform;
- mp->_source = CFRunLoopSourceCreate(allocator, order, (CFRunLoopSourceContext *)&context);
- }
- result = mp->_source ? (CFRunLoopSourceRef)CFRetain(mp->_source) : NULL;
- });
+ CFRunLoopSourceRef result = NULL;
+ __CFSpinLock(&mp->_lock);
+ if (__CFMachPortIsValid(mp)) {
+ if (NULL != mp->_source && !CFRunLoopSourceIsValid(mp->_source)) {
+ CFRelease(mp->_source);
+ mp->_source = NULL;
+ }
+ if (NULL == mp->_source) {
+ CFRunLoopSourceContext1 context;
+ context.version = 1;
+ context.info = (void *)mp;
+ context.retain = (const void *(*)(const void *))CFRetain;
+ context.release = (void (*)(const void *))CFRelease;
+ context.copyDescription = (CFStringRef (*)(const void *))__CFMachPortCopyDescription;
+ context.equal = (Boolean (*)(const void *, const void *))__CFMachPortEqual;
+ context.hash = (CFHashCode (*)(const void *))__CFMachPortHash;
+ context.getPort = __CFMachPortGetPort;
+ context.perform = __CFMachPortPerform;
+ mp->_source = CFRunLoopSourceCreate(allocator, order, (CFRunLoopSourceContext *)&context);
+ }
+ result = mp->_source ? (CFRunLoopSourceRef)CFRetain(mp->_source) : NULL;
+ }
+ __CFSpinUnlock(&mp->_lock);
return result;
}
*/
/* CFMachPort.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFMACHPORT__)
*/
/* CFMessagePort.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
#include <mach/mach_time.h>
#include <dlfcn.h>
#include <dispatch/dispatch.h>
+#include <dispatch/private.h>
extern pid_t getpid(void);
#define __CFMessagePortMaxDataSize 0x60000000L
-//#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-DISPATCH_HELPER_FUNCTIONS(mport, CFMessagePort)
-//#pragma GCC diagnostic pop
-
-
static CFSpinLock_t __CFAllMessagePortsLock = CFSpinLockInit;
static CFMutableDictionaryRef __CFAllLocalMessagePorts = NULL;
static CFMutableDictionaryRef __CFAllRemoteMessagePorts = NULL;
utfname = CFAllocatorAllocate(kCFAllocatorSystemDefault, __kCFMessagePortMaxNameLength + 1, 0);
CFStringGetBytes(name, CFRangeMake(0, CFStringGetLength(name)), kCFStringEncodingUTF8, 0, false, utfname, __kCFMessagePortMaxNameLength, &utflen);
utfname[utflen] = '\0';
- if (strlen(utfname) != utflen) {
+ if (strlen((const char *)utfname) != utflen) {
/* PCA 9194709: refuse to sanitize a string with an embedded nul character */
CFAllocatorDeallocate(kCFAllocatorSystemDefault, utfname);
utfname = NULL;
}
CFDictionaryAddValue(__CFAllRemoteMessagePorts, name, memory);
}
+ CFRetain(native);
__CFSpinUnlock(&__CFAllMessagePortsLock);
CFMachPortSetInvalidationCallBack(native, __CFMessagePortInvalidationCallBack);
// that set-invalidation-callback might have called back into us
// went invalid; so check for validity manually and react
if (!CFMachPortIsValid(native)) {
CFRelease(memory); // does the invalidate
+ CFRelease(native);
return NULL;
}
+ CFRelease(native);
return (CFMessagePortRef)memory;
}
__CFMessagePortUnlock(ms);
__CFSpinLock(&__CFAllMessagePortsLock);
- if (0 == ms->_perPID && NULL != (__CFMessagePortIsRemote(ms) ? __CFAllRemoteMessagePorts : __CFAllLocalMessagePorts)) {
+ if (0 == ms->_perPID && NULL != name && NULL != (__CFMessagePortIsRemote(ms) ? __CFAllRemoteMessagePorts : __CFAllLocalMessagePorts)) {
CFDictionaryRemoveValue(__CFMessagePortIsRemote(ms) ? __CFAllRemoteMessagePorts : __CFAllLocalMessagePorts, name);
}
__CFSpinUnlock(&__CFAllMessagePortsLock);
Boolean CFMessagePortIsValid(CFMessagePortRef ms) {
__CFGenericValidateType(ms, __kCFMessagePortTypeID);
if (!__CFMessagePortIsValid(ms)) return false;
+ CFRetain(ms);
if (NULL != ms->_port && !CFMachPortIsValid(ms->_port)) {
CFMessagePortInvalidate(ms);
+ CFRelease(ms);
return false;
}
if (NULL != ms->_replyPort && !CFMachPortIsValid(ms->_replyPort)) {
CFMessagePortInvalidate(ms);
+ CFRelease(ms);
return false;
}
+ CFRelease(ms);
return true;
}
if (sendTimeout < 1.0) sendTimeout = 0.0;
sendTimeOut = floor(sendTimeout);
}
+ __CFMessagePortUnlock(remote);
ret = mach_msg((mach_msg_header_t *)sendmsg, MACH_SEND_MSG|sendOpts, sendmsg->header.msgh_size, 0, MACH_PORT_NULL, sendTimeOut, MACH_PORT_NULL);
+ __CFMessagePortLock(remote);
if (KERN_SUCCESS != ret) {
// need to deallocate the send-once right that might have been created
if (replyMode != NULL) mach_port_deallocate(mach_task_self(), ((mach_msg_header_t *)sendmsg)->msgh_local_port);
if (queue) {
mach_port_t port = __CFMessagePortGetPort(ms);
if (MACH_PORT_NULL != port) {
- dispatch_source_t theSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, port, 0, __mportQueue());
- dispatch_source_set_cancel_handler(theSource, ^{
- dispatch_release(queue);
- dispatch_release(theSource);
- });
- dispatch_source_set_event_handler(theSource, ^{
- CFRetain(ms);
- mach_msg_header_t *msg = (mach_msg_header_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2048, 0);
- msg->msgh_size = 2048;
-
- for (;;) {
- msg->msgh_bits = 0;
- msg->msgh_local_port = port;
- msg->msgh_remote_port = MACH_PORT_NULL;
- msg->msgh_id = 0;
-
- kern_return_t ret = mach_msg(msg, MACH_RCV_MSG|MACH_RCV_LARGE|MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV), 0, msg->msgh_size, port, 0, MACH_PORT_NULL);
- if (MACH_MSG_SUCCESS == ret) break;
- if (MACH_RCV_TOO_LARGE != ret) HALT;
-
- uint32_t newSize = round_msg(msg->msgh_size + MAX_TRAILER_SIZE);
- msg = CFAllocatorReallocate(kCFAllocatorSystemDefault, msg, newSize, 0);
- msg->msgh_size = newSize;
- }
-
- dispatch_async(queue, ^{
- mach_msg_header_t *reply = __CFMessagePortPerform(msg, msg->msgh_size, kCFAllocatorSystemDefault, ms);
- if (NULL != reply) {
- kern_return_t ret = mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
- if (KERN_SUCCESS != ret) mach_msg_destroy(reply);
- CFAllocatorDeallocate(kCFAllocatorSystemDefault, reply);
- }
- CFAllocatorDeallocate(kCFAllocatorSystemDefault, msg);
- CFRelease(ms);
- });
- });
- ms->_dispatchSource = theSource;
- }
+ static dispatch_queue_t mportQueue = NULL;
+ static dispatch_once_t once;
+ dispatch_once(&once, ^{
+ mportQueue = dispatch_queue_create("CFMessagePort Queue", NULL);
+ });
+ dispatch_source_t theSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, port, 0, mportQueue);
+ dispatch_source_set_cancel_handler(theSource, ^{
+ dispatch_release(queue);
+ dispatch_release(theSource);
+ });
+ dispatch_source_set_event_handler(theSource, ^{
+ CFRetain(ms);
+ mach_msg_header_t *msg = (mach_msg_header_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 2048, 0);
+ msg->msgh_size = 2048;
+
+ for (;;) {
+ msg->msgh_bits = 0;
+ msg->msgh_local_port = port;
+ msg->msgh_remote_port = MACH_PORT_NULL;
+ msg->msgh_id = 0;
+
+ kern_return_t ret = mach_msg(msg, MACH_RCV_MSG|MACH_RCV_LARGE|MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV), 0, msg->msgh_size, port, 0, MACH_PORT_NULL);
+ if (MACH_MSG_SUCCESS == ret) break;
+ if (MACH_RCV_TOO_LARGE != ret) HALT;
+
+ uint32_t newSize = round_msg(msg->msgh_size + MAX_TRAILER_SIZE);
+ msg = CFAllocatorReallocate(kCFAllocatorSystemDefault, msg, newSize, 0);
+ msg->msgh_size = newSize;
+ }
+
+ dispatch_async(queue, ^{
+ mach_msg_header_t *reply = __CFMessagePortPerform(msg, msg->msgh_size, kCFAllocatorSystemDefault, ms);
+ if (NULL != reply) {
+ kern_return_t ret = mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
+ if (KERN_SUCCESS != ret) mach_msg_destroy(reply);
+ CFAllocatorDeallocate(kCFAllocatorSystemDefault, reply);
+ }
+ CFAllocatorDeallocate(kCFAllocatorSystemDefault, msg);
+ CFRelease(ms);
+ });
+ });
+ ms->_dispatchSource = theSource;
+ }
if (ms->_dispatchSource) {
dispatch_retain(queue);
ms->_dispatchQ = queue;
*/
/* CFMessagePort.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFMESSAGEPORT__)
*/
/* CFNumber.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Ali Ozer
*/
#include <math.h>
#include <float.h>
+
#if DEPLOYMENT_TARGET_WINDOWS
#define isnan(A) _isnan(A)
#define isinf(A) !_finite(A)
}
Boolean CFBooleanGetValue(CFBooleanRef boolean) {
- CF_OBJC_FUNCDISPATCH0(__kCFBooleanTypeID, Boolean, boolean, "boolValue");
+ CF_OBJC_FUNCDISPATCHV(__kCFBooleanTypeID, Boolean, (NSNumber *)boolean, boolValue);
return (boolean == kCFBooleanTrue) ? true : false;
}
#if OLD_CRAP_TOO
+// old implementation, for runtime comparison purposes
+
typedef union {
SInt32 valSInt32;
int64_t valSInt64;
#define BITSFORDOUBLEPOSINF ((uint64_t)0x7ff0000000000000ULL)
#define BITSFORDOUBLENEGINF ((uint64_t)0xfff0000000000000ULL)
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
#define FLOAT_POSITIVE_2_TO_THE_64 0x1.0p+64L
#define FLOAT_NEGATIVE_2_TO_THE_127 -0x1.0p+127L
#define FLOAT_POSITIVE_2_TO_THE_127 0x1.0p+127L
__CFNumberCopyDescription
};
+
__private_extern__ void __CFNumberInitialize(void) {
__kCFNumberTypeID = _CFRuntimeRegisterClass(&__CFNumberClass);
case kCFNumberSInt32Type: {
int32_t value = *(int32_t *)valuePtr;
#if !__LP64__
- // We don't bother allowing the min 24-bit integer -2^24 to also be fast-pathed;
+ // 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.
- if ((1L << 23) <= -value || (1L << 23) <= value) break;
+ int32_t limit = (1L << 23);
+ if (value <= -limit || limit <= value) break;
#endif
- return (CFNumberRef)((uintptr_t)((intptr_t)value << 8) | (2 << 6) | kCFTaggedObjectID_Integer);
+ uintptr_t ptr_val = ((uintptr_t)((intptr_t)value << 8) | (2 << 6) | kCFTaggedObjectID_Integer);
+ return (CFNumberRef)ptr_val;
}
-#if __LP64__
case kCFNumberSInt64Type: {
int64_t value = *(int64_t *)valuePtr;
- // We don't bother allowing the min 56-bit integer -2^56 to also be fast-pathed;
+#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.
- if ((1L << 55) <= -value || (1L << 55) <= value) break;
- uintptr_t ptr_val = ((uintptr_t)(value << 8) | (3 << 6) | kCFTaggedObjectID_Integer);
+ 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;
}
-#endif
}
}
if (CF_IS_TAGGED_INT(number)) {
return __CFNumberGetType(number);
}
- CF_OBJC_FUNCDISPATCH0(__kCFNumberTypeID, CFNumberType, number, "_cfNumberType");
+ CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFNumberType, (NSNumber *)number, _cfNumberType);
__CFAssertIsNumber(number);
CFNumberType type = __CFNumberGetType(number);
if (kCFNumberSInt128Type == type) type = kCFNumberSInt64Type; // must hide this type, since it is not public
Boolean r = __CFNumberGetValueCompat(number, type, valuePtr);
return r;
}
- CF_OBJC_FUNCDISPATCH2(__kCFNumberTypeID, Boolean, number, "_getValue:forType:", valuePtr, __CFNumberTypeTable[type].canonicalType);
+ CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, Boolean, (NSNumber *)number, _getValue:(void *)valuePtr forType:(CFNumberType)__CFNumberTypeTable[type].canonicalType);
__CFAssertIsNumber(number);
__CFAssertIsValidNumberType(type);
uint8_t localMemory[128];
}
static CFComparisonResult CFNumberCompare_new(CFNumberRef number1, CFNumberRef number2, void *context) {
- CF_OBJC_FUNCDISPATCH1(__kCFNumberTypeID, CFComparisonResult, number1, "compare:", number2);
- CF_OBJC_FUNCDISPATCH1(__kCFNumberTypeID, CFComparisonResult, number2, "_reverseCompare:", number1);
+ CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFComparisonResult, (NSNumber *)number1, compare:(NSNumber *)number2);
+ CF_OBJC_FUNCDISPATCHV(__kCFNumberTypeID, CFComparisonResult, (NSNumber *)number2, _reverseCompare:(NSNumber *)number1);
__CFAssertIsNumber(number1);
__CFAssertIsNumber(number2);
*/
/* CFNumber.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFNUMBER__)
#include <CoreFoundation/CFBase.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
typedef const struct __CFBoolean * CFBooleanRef;
CF_EXPORT
Boolean CFBooleanGetValue(CFBooleanRef boolean);
-enum {
+typedef CF_ENUM(CFIndex, CFNumberType) {
/* Fixed-width types */
kCFNumberSInt8Type = 1,
kCFNumberSInt16Type = 2,
kCFNumberDoubleType = 13,
/* Other */
kCFNumberCFIndexType = 14,
-#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
- kCFNumberNSIntegerType = 15,
- kCFNumberCGFloatType = 16,
+ kCFNumberNSIntegerType CF_ENUM_AVAILABLE(10_5, 2_0) = 15,
+ kCFNumberCGFloatType CF_ENUM_AVAILABLE(10_5, 2_0) = 16,
kCFNumberMaxType = 16
-#else
- kCFNumberMaxType = 14
-#endif
};
-typedef CFIndex CFNumberType;
typedef const struct __CFNumber * CFNumberRef;
CFComparisonResult CFNumberCompare(CFNumberRef number, CFNumberRef otherNumber, void *context);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFNUMBER__ */
*/
/* CFNumberFormatter.c
- Copyright (c) 2002-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2002-2012, Apple Inc. All rights reserved.
Responsibility: David Smith
*/
#include <CoreFoundation/CFNumberFormatter.h>
#include <CoreFoundation/ForFoundationOnly.h>
+#include <CoreFoundation/CFBigNumber.h>
#include "CFInternal.h"
#include "CFLocaleInternal.h"
#include <unicode/unum.h>
#include <math.h>
#include <float.h>
+
static void __CFNumberFormatterCustomize(CFNumberFormatterRef formatter);
static CFStringRef __CFNumberFormatterCreateCompressedString(CFStringRef inString, Boolean isFormat, CFRange *rangep);
static UErrorCode __CFNumberFormatterApplyPattern(CFNumberFormatterRef formatter, CFStringRef pattern);
}
}
+#define GET_MULTIPLIER \
+ double multiplier = 1.0; \
+ double dummy = 0.0; \
+ if (formatter->_multiplier) { \
+ if (!CFNumberGetValue(formatter->_multiplier, kCFNumberFloat64Type, &multiplier)) { \
+ multiplier = 1.0; \
+ } \
+ } \
+ if (modf(multiplier, &dummy) < FLT_EPSILON) { \
+ multiplier = floor(multiplier); \
+ }
+
CFStringRef CFNumberFormatterCreateStringWithNumber(CFAllocatorRef allocator, CFNumberFormatterRef formatter, CFNumberRef number) {
if (allocator == NULL) allocator = __CFGetDefaultAllocator();
__CFGenericValidateType(allocator, CFAllocatorGetTypeID());
return CFNumberFormatterCreateStringWithValue(allocator, formatter, type, buffer);
}
-#define FORMAT(T, FUNC) \
+#define FORMAT_FLT(T, FUNC) \
T value = *(T *)valuePtr; \
if (0 == value && formatter->_zeroSym) { return (CFStringRef)CFRetain(formatter->_zeroSym); } \
if (1.0 != multiplier) { \
- double dummy; \
- if (modf(multiplier, &dummy) < FLT_EPSILON) { /* float epsilon specifically chosen cuz it is a bit bigger */ \
- value = value * (T)floor(multiplier); \
- } else { \
- value = (T)(value * multiplier); \
- } \
+ value = (T)(value * multiplier); \
} \
status = U_ZERO_ERROR; \
used = FUNC(formatter->_nf, value, ubuffer, cnt, NULL, &status); \
used = FUNC(formatter->_nf, value, ustr, cnt, NULL, &status); \
}
+#define FORMAT_INT(T, FUN) \
+ T value = *(T *)valuePtr; \
+ if (0 == value && formatter->_zeroSym) { return (CFStringRef)CFRetain(formatter->_zeroSym); } \
+ if (1.0 != multiplier) { \
+ value = (T)(value * multiplier); \
+ } \
+ _CFBigNum bignum; \
+ FUN(&bignum, value); \
+ char buffer[BUFFER_SIZE]; \
+ _CFBigNumToCString(&bignum, false, true, buffer, BUFFER_SIZE); \
+ status = U_ZERO_ERROR; \
+ used = unum_formatDecimal(formatter->_nf, buffer, strlen(buffer), ubuffer, BUFFER_SIZE, NULL, &status); \
+ if (status == U_BUFFER_OVERFLOW_ERROR || cnt < used) { \
+ cnt = used + 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); \
+ } \
+
CFStringRef CFNumberFormatterCreateStringWithValue(CFAllocatorRef allocator, CFNumberFormatterRef formatter, CFNumberType numberType, const void *valuePtr) {
if (allocator == NULL) allocator = __CFGetDefaultAllocator();
__CFGenericValidateType(allocator, CFAllocatorGetTypeID());
__CFGenericValidateType(formatter, CFNumberFormatterGetTypeID());
- double multiplier = 1.0;
- if (formatter->_multiplier) {
- if (!CFNumberGetValue(formatter->_multiplier, kCFNumberFloat64Type, &multiplier)) {
- multiplier = 1.0;
- }
- }
+ GET_MULTIPLIER;
UChar *ustr = NULL, ubuffer[BUFFER_SIZE];
UErrorCode status = U_ZERO_ERROR;
CFIndex used, cnt = BUFFER_SIZE;
if (numberType == kCFNumberFloat64Type || numberType == kCFNumberDoubleType) {
- FORMAT(double, unum_formatDouble)
+ FORMAT_FLT(double, unum_formatDouble)
} else if (numberType == kCFNumberFloat32Type || numberType == kCFNumberFloatType) {
- FORMAT(float, unum_formatDouble)
+ FORMAT_FLT(float, unum_formatDouble)
} else if (numberType == kCFNumberSInt64Type || numberType == kCFNumberLongLongType) {
- FORMAT(int64_t, unum_formatInt64)
+ FORMAT_INT(int64_t, _CFBigNumInitWithInt64)
} else if (numberType == kCFNumberLongType || numberType == kCFNumberCFIndexType) {
#if __LP64__
- FORMAT(int64_t, unum_formatInt64)
+ FORMAT_INT(int64_t, _CFBigNumInitWithInt64)
#else
- FORMAT(int32_t, unum_formatInt64)
+ FORMAT_INT(int32_t, _CFBigNumInitWithInt32)
#endif
} else if (numberType == kCFNumberSInt32Type || numberType == kCFNumberIntType) {
- FORMAT(int32_t, unum_formatInt64)
+ FORMAT_INT(int32_t, _CFBigNumInitWithInt32)
} else if (numberType == kCFNumberSInt16Type || numberType == kCFNumberShortType) {
- FORMAT(int16_t, unum_formatInt64)
+ FORMAT_INT(int16_t, _CFBigNumInitWithInt16)
} else if (numberType == kCFNumberSInt8Type || numberType == kCFNumberCharType) {
- FORMAT(int8_t, unum_formatInt64)
+ FORMAT_INT(int8_t, _CFBigNumInitWithInt8)
} else {
CFAssert2(0, __kCFLogAssertion, "%s(): unknown CFNumberType (%d)", __PRETTY_FUNCTION__, numberType);
return NULL;
return string;
}
-#undef FORMAT
+#undef FORMAT_FLT
+#undef FORMAT_INT
+#undef GET_MULTIPLIER
CFNumberRef CFNumberFormatterCreateNumberFromString(CFAllocatorRef allocator, CFNumberFormatterRef formatter, CFStringRef string, CFRange *rangep, CFOptionFlags options) {
if (allocator == NULL) allocator = __CFGetDefaultAllocator();
__CFGenericValidateType(allocator, CFAllocatorGetTypeID());
__CFGenericValidateType(formatter, CFNumberFormatterGetTypeID());
__CFGenericValidateType(string, CFStringGetTypeID());
- CFNumberType type = (options & kCFNumberFormatterParseIntegersOnly) ? kCFNumberSInt64Type : kCFNumberFloat64Type;
- char buffer[16];
- if (CFNumberFormatterGetValueFromString(formatter, string, rangep, type, buffer)) {
- return CFNumberCreate(allocator, type, buffer);
+ char buffer[16] __attribute__ ((aligned (8)));
+ CFRange r = rangep ? *rangep : CFRangeMake(0, CFStringGetLength(string));
+ CFNumberRef multiplierRef = formatter->_multiplier;
+ formatter->_multiplier = NULL;
+ Boolean b = CFNumberFormatterGetValueFromString(formatter, string, &r, kCFNumberSInt64Type, buffer);
+ formatter->_multiplier = multiplierRef;
+ if (b) {
+ Boolean passedMultiplier = true;
+ // We handle the multiplier case here manually; the final
+ // result is supposed to be (parsed value) / (multiplier), but
+ // the int case here should only succeed if the parsed value
+ // is an exact multiple of the multiplier.
+ if (multiplierRef) {
+ int64_t tmp = *(int64_t *)buffer;
+ double multiplier = 1.0;
+ if (!CFNumberGetValue(multiplierRef, kCFNumberFloat64Type, &multiplier)) {
+ multiplier = 1.0;
+ }
+ double dummy;
+ if (llabs(tmp) < fabs(multiplier)) {
+ passedMultiplier = false;
+ } else if (fabs(multiplier) < 1.0) { // We can't handle this math yet
+ passedMultiplier = false;
+ } else if (modf(multiplier, &dummy) == 0.0) { // multiplier is an integer
+ int64_t imult = (int64_t)multiplier;
+ int64_t rem = tmp % imult;
+ if (rem != 0) passedMultiplier = false;
+ if (passedMultiplier) {
+ tmp = tmp / imult;
+ *(int64_t *)buffer = tmp;
+ }
+ } else if (multiplier == -1.0) { // simple
+ tmp = tmp * -1;
+ *(int64_t *)buffer = tmp;
+ } else if (multiplier != 1.0) {
+ // First, throw away integer multiples of the multiplier to
+ // bring the value down to less than 2^53, so that we can
+ // cast it to double without losing any precision, important
+ // for the "remainder is zero" test.
+ // Find power of two which, when multiplier is multiplied by it,
+ // results in an integer value. pwr will be <= 52 since multiplier
+ // is at least 1.
+ int pwr = 0;
+ double intgrl;
+ while (modf(scalbn(multiplier, pwr), &intgrl) != 0.0) pwr++;
+ int64_t i2 = (int64_t)intgrl;
+ // scale pwr and i2 up to a reasonably large value so the next loop doesn't take forever
+ while (llabs(i2) < (1LL << 50)) { i2 *= 2; pwr++; }
+ int64_t cnt = 0;
+ while ((1LL << 53) <= llabs(tmp)) {
+ // subtract (multiplier * 2^pwr) each time
+ tmp -= i2; // move tmp toward zero
+ cnt += (1LL << pwr); // remember how many 2^pwr we subtracted
+ }
+ // If the integer is less than 2^53, there is no loss
+ // in converting it to double, so we can just do the
+ // direct operation now.
+ double rem = fmod((double)tmp, multiplier);
+ if (rem != 0.0) passedMultiplier = false;
+ if (passedMultiplier) {
+ // The original tmp, which we need to divide by multiplier, is at this point:
+ // tmp + k * 2^n * multiplier, where k is the number of loop iterations
+ // That original value needs to be divided by multiplier and put back in the
+ // buffer. Noting that k * 2^n == cnt, and after some algebra, we have:
+ tmp = (int64_t)((double)tmp / multiplier) + cnt;
+ *(int64_t *)buffer = tmp;
+ }
+ }
+ }
+ if (passedMultiplier && ((r.length == CFStringGetLength(string)) || (options & kCFNumberFormatterParseIntegersOnly))) {
+ if (rangep) *rangep = r;
+ return CFNumberCreate(allocator, kCFNumberSInt64Type, buffer);
+ }
+ }
+ if (options & kCFNumberFormatterParseIntegersOnly) return NULL;
+ if (CFNumberFormatterGetValueFromString(formatter, string, rangep, kCFNumberFloat64Type, buffer)) {
+ return CFNumberCreate(allocator, kCFNumberFloat64Type, buffer);
}
return NULL;
}
} else if (!formatter->_isLenient) {
ustr += range.location;
}
- if (formatter->_isLenient) __CFNumberFormatterApplyPattern(formatter, formatter->_compformat);
+ CFNumberRef multiplierRef = formatter->_multiplier;
+ formatter->_multiplier = NULL;
+ if (formatter->_isLenient) {
+ __CFNumberFormatterApplyPattern(formatter, formatter->_compformat);
+ if (formatter->_multiplier) CFRelease(formatter->_multiplier);
+ formatter->_multiplier = NULL;
+ }
Boolean integerOnly = 1;
switch (numberType) {
case kCFNumberSInt8Type: case kCFNumberCharType:
if (isZero) {
dpos = rangep ? rangep->length : 0;
} else {
- if (integerOnly) {
- dreti = unum_parseInt64(formatter->_nf, ustr, range.length, &dpos, &status);
- } else {
- dretd = unum_parseDouble(formatter->_nf, ustr, range.length, &dpos, &status);
+ char buffer[1024];
+ memset(buffer, 0, sizeof(buffer));
+ int32_t len = unum_parseDecimal(formatter->_nf, ustr, range.length, &dpos, buffer, sizeof(buffer), &status);
+ if (!U_FAILURE(status) && 0 < len && integerOnly) {
+ char *endptr = NULL;
+ errno = 0;
+ dreti = strtoll_l(buffer, &endptr, 10, NULL);
+ if (!(errno == 0 && *endptr == '\0')) status = U_INVALID_FORMAT_ERROR;
+ }
+ if (!U_FAILURE(status) && 0 < len) {
+ char *endptr = NULL;
+ errno = 0;
+ dretd = strtod_l(buffer, &endptr, NULL);
+ if (!(errno == 0 && *endptr == '\0')) status = U_INVALID_FORMAT_ERROR;
}
}
if (formatter->_isLenient) {
rangep->length = uncompIdx - rangep->location;
}
__CFNumberFormatterApplyPattern(formatter, formatter->_format);
+ if (formatter->_multiplier) CFRelease(formatter->_multiplier);
+ formatter->_multiplier = NULL;
} else if (rangep) {
rangep->length = dpos + (range.location - rangep->location);
}
+ formatter->_multiplier = multiplierRef;
CFRelease(stringToParse);
if (U_FAILURE(status)) {
return false;
if (!CFNumberGetValue(formatter->_multiplier, kCFNumberFloat64Type, &multiplier)) {
multiplier = 1.0;
}
- dreti = (int64_t)((double)dreti / multiplier); // integer truncation
+ dreti = (int64_t)((double)dreti / multiplier); // integer truncation, plus double cast can be lossy for dreti > 2^53
dretd = dretd / multiplier;
}
switch (numberType) {
*/
/* CFNumberFormatter.h
- Copyright (c) 2003-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2003-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFNUMBERFORMATTER__)
CF_EXPORT
CFTypeID CFNumberFormatterGetTypeID(void);
-enum { // number format styles
+typedef CF_ENUM(CFIndex, CFNumberFormatterStyle) { // number format styles
kCFNumberFormatterNoStyle = 0,
kCFNumberFormatterDecimalStyle = 1,
kCFNumberFormatterCurrencyStyle = 2,
kCFNumberFormatterScientificStyle = 4,
kCFNumberFormatterSpellOutStyle = 5
};
-typedef CFIndex CFNumberFormatterStyle;
CF_EXPORT
// Set the format description string of the number formatter. This
// overrides the style settings. The format of the format string
// is as defined by the ICU library, and is similar to that found
- // in Microsoft Excel and NSNumberFormatter (and Java I believe).
+ // in Microsoft Excel and NSNumberFormatter.
// The number formatter starts with a default format string defined
// by the style argument with which it was created.
// using the current state of the number formatter.
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFNumberFormatterOptionFlags) {
kCFNumberFormatterParseIntegersOnly = 1 /* only parse integers */
};
-typedef CFOptionFlags CFNumberFormatterOptionFlags;
CF_EXPORT
CFNumberRef CFNumberFormatterCreateNumberFromString(CFAllocatorRef allocator, CFNumberFormatterRef formatter, CFStringRef string, CFRange *rangep, CFOptionFlags options);
CF_EXPORT const CFStringRef kCFNumberFormatterMinSignificantDigits CF_AVAILABLE(10_5, 2_0); // CFNumber
CF_EXPORT const CFStringRef kCFNumberFormatterMaxSignificantDigits CF_AVAILABLE(10_5, 2_0); // CFNumber
-enum {
+typedef CF_ENUM(CFIndex, CFNumberFormatterRoundingMode) {
kCFNumberFormatterRoundCeiling = 0,
kCFNumberFormatterRoundFloor = 1,
kCFNumberFormatterRoundDown = 2,
kCFNumberFormatterRoundHalfDown = 5,
kCFNumberFormatterRoundHalfUp = 6
};
-typedef CFIndex CFNumberFormatterRoundingMode;
-enum {
+typedef CF_ENUM(CFIndex, CFNumberFormatterPadPosition) {
kCFNumberFormatterPadBeforePrefix = 0,
kCFNumberFormatterPadAfterPrefix = 1,
kCFNumberFormatterPadBeforeSuffix = 2,
kCFNumberFormatterPadAfterSuffix = 3
};
-typedef CFIndex CFNumberFormatterPadPosition;
CF_EXPORT
--- /dev/null
+/*
+ * Copyright (c) 2012 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@
+ */
+
+/* CFOldStylePList.c
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
+ Responsibility: Tony Parker
+*/
+
+#include <CoreFoundation/CFPropertyList.h>
+#include <CoreFoundation/CFDate.h>
+#include <CoreFoundation/CFNumber.h>
+#include <CoreFoundation/CFError.h>
+#include <CoreFoundation/CFStringEncodingConverter.h>
+#include "CFInternal.h"
+#include <CoreFoundation/CFCalendar.h>
+#include <CoreFoundation/CFSet.h>
+
+#include <ctype.h>
+
+//
+// Old NeXT-style property lists
+//
+
+CF_INLINE void __CFPListRelease(CFTypeRef cf, CFAllocatorRef allocator) {
+ if (cf && !_CFAllocatorIsGCRefZero(allocator)) CFRelease(cf);
+}
+
+__private_extern__ CFErrorRef __CFPropertyListCreateError(CFIndex code, CFStringRef debugString, ...);
+
+typedef struct {
+ const UniChar *begin;
+ const UniChar *curr;
+ const UniChar *end;
+ CFErrorRef error;
+ CFAllocatorRef allocator;
+ UInt32 mutabilityOption;
+ CFMutableSetRef stringSet; // set of all strings involved in this parse; allows us to share non-mutable strings in the returned plist
+} _CFStringsFileParseInfo;
+
+// warning: doesn't have a good idea of Unicode line separators
+static UInt32 lineNumberStrings(_CFStringsFileParseInfo *pInfo) {
+ const UniChar *p = pInfo->begin;
+ UInt32 count = 1;
+ while (p < pInfo->curr) {
+ if (*p == '\r') {
+ count ++;
+ if (*(p + 1) == '\n')
+ p ++;
+ } else if (*p == '\n') {
+ count ++;
+ }
+ p ++;
+ }
+ return count;
+}
+
+static CFTypeRef parsePlistObject(_CFStringsFileParseInfo *pInfo, bool requireObject);
+
+#define isValidUnquotedStringCharacter(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || ((x) >= '0' && (x) <= '9') || (x) == '_' || (x) == '$' || (x) == '/' || (x) == ':' || (x) == '.' || (x) == '-')
+
+// Returns true if the advance found something before the end of the buffer, false otherwise
+static Boolean advanceToNonSpace(_CFStringsFileParseInfo *pInfo) {
+ UniChar ch2;
+ while (pInfo->curr < pInfo->end) {
+ ch2 = *(pInfo->curr);
+ pInfo->curr ++;
+ if (ch2 >= 9 && ch2 <= 0x0d) continue; // tab, newline, vt, form feed, carriage return
+ if (ch2 == ' ' || ch2 == 0x2028 || ch2 == 0x2029) continue; // space and Unicode line sep, para sep
+ if (ch2 == '/') {
+ if (pInfo->curr >= pInfo->end) {
+ // whoops; back up and return
+ pInfo->curr --;
+ return true;
+ } else if (*(pInfo->curr) == '/') {
+ pInfo->curr ++;
+ while (pInfo->curr < pInfo->end) { // go to end of comment line
+ UniChar ch3 = *(pInfo->curr);
+ if (ch3 == '\n' || ch3 == '\r' || ch3 == 0x2028 || ch3 == 0x2029) break;
+ pInfo->curr ++;
+ }
+ } else if (*(pInfo->curr) == '*') { // handle /* ... */
+ pInfo->curr ++;
+ while (pInfo->curr < pInfo->end) {
+ ch2 = *(pInfo->curr);
+ pInfo->curr ++;
+ if (ch2 == '*' && pInfo->curr < pInfo->end && *(pInfo->curr) == '/') {
+ pInfo->curr ++; // advance past the '/'
+ break;
+ }
+ }
+ } else {
+ pInfo->curr --;
+ return true;
+ }
+ } else {
+ pInfo->curr --;
+ return true;
+ }
+ }
+ return false;
+}
+
+static UniChar getSlashedChar(_CFStringsFileParseInfo *pInfo) {
+ UniChar ch = *(pInfo->curr);
+ pInfo->curr ++;
+ switch (ch) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7': {
+ uint8_t num = ch - '0';
+ UniChar result;
+ CFIndex usedCharLen;
+ /* three digits maximum to avoid reading \000 followed by 5 as \5 ! */
+ if ((ch = *(pInfo->curr)) >= '0' && ch <= '7') { // we use in this test the fact that the buffer is zero-terminated
+ pInfo->curr ++;
+ num = (num << 3) + ch - '0';
+ if ((pInfo->curr < pInfo->end) && (ch = *(pInfo->curr)) >= '0' && ch <= '7') {
+ pInfo->curr ++;
+ num = (num << 3) + ch - '0';
+ }
+ }
+ CFStringEncodingBytesToUnicode(kCFStringEncodingNextStepLatin, 0, &num, sizeof(uint8_t), NULL, &result, 1, &usedCharLen);
+ return (usedCharLen == 1) ? result : 0;
+ }
+ case 'U': {
+ unsigned num = 0, numDigits = 4; /* Parse four digits */
+ while (pInfo->curr < pInfo->end && numDigits--) {
+ if (((ch = *(pInfo->curr)) < 128) && isxdigit(ch)) {
+ pInfo->curr ++;
+ num = (num << 4) + ((ch <= '9') ? (ch - '0') : ((ch <= 'F') ? (ch - 'A' + 10) : (ch - 'a' + 10)));
+ }
+ }
+ return num;
+ }
+ case 'a': return '\a'; // Note: the meaning of '\a' varies with -traditional to gcc
+ case 'b': return '\b';
+ case 'f': return '\f';
+ case 'n': return '\n';
+ case 'r': return '\r';
+ case 't': return '\t';
+ case 'v': return '\v';
+ case '"': return '\"';
+ case '\n': return '\n';
+ }
+ return ch;
+}
+
+static CFStringRef _uniqueStringForCharacters(_CFStringsFileParseInfo *pInfo, const UniChar *base, CFIndex length) {
+ if (0 == length) return !_CFAllocatorIsGCRefZero(pInfo->allocator) ? (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;
+ Boolean use_stack = (length < 2048);
+ STACK_BUFFER_DECL(uint8_t, buffer, use_stack ? length + 1 : 1);
+ uint8_t *ascii = use_stack ? buffer : (uint8_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, length + 1, 0);
+ for (CFIndex idx = 0; idx < length; idx++) {
+ UniChar ch = base[idx];
+ if (ch < 0x80) {
+ ascii[idx] = (uint8_t)ch;
+ } else {
+ stringToUnique = CFStringCreateWithCharacters(pInfo->allocator, base, length);
+ break;
+ }
+ }
+ if (!stringToUnique) {
+ ascii[length] = '\0';
+ stringToUnique = CFStringCreateWithBytes(pInfo->allocator, ascii, length, kCFStringEncodingASCII, false);
+ }
+ if (ascii != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, ascii);
+ CFStringRef uniqued = (CFStringRef)CFSetGetValue(pInfo->stringSet, stringToUnique);
+ if (!uniqued) {
+ CFSetAddValue(pInfo->stringSet, stringToUnique);
+ uniqued = stringToUnique;
+ }
+ __CFPListRelease(stringToUnique, pInfo->allocator);
+ if (uniqued && !_CFAllocatorIsGCRefZero(pInfo->allocator)) CFRetain(uniqued);
+ return uniqued;
+}
+
+static CFStringRef _uniqueStringForString(_CFStringsFileParseInfo *pInfo, CFStringRef stringToUnique) {
+ CFStringRef uniqued = (CFStringRef)CFSetGetValue(pInfo->stringSet, stringToUnique);
+ if (!uniqued) {
+ uniqued = (CFStringRef)__CFStringCollectionCopy(pInfo->allocator, stringToUnique);
+ CFSetAddValue(pInfo->stringSet, uniqued);
+ __CFTypeCollectionRelease(pInfo->allocator, uniqued);
+ }
+ if (uniqued && !_CFAllocatorIsGCRefZero(pInfo->allocator)) CFRetain(uniqued);
+ return uniqued;
+}
+
+static CFStringRef parseQuotedPlistString(_CFStringsFileParseInfo *pInfo, UniChar quote) {
+ CFMutableStringRef str = NULL;
+ const UniChar *startMark = pInfo->curr;
+ const UniChar *mark = pInfo->curr;
+ while (pInfo->curr < pInfo->end) {
+ UniChar ch = *(pInfo->curr);
+ if (ch == quote) break;
+ if (ch == '\\') {
+ if (!str) str = CFStringCreateMutable(pInfo->allocator, 0);
+ CFStringAppendCharacters(str, mark, pInfo->curr - mark);
+ pInfo->curr ++;
+ ch = getSlashedChar(pInfo);
+ CFStringAppendCharacters(str, &ch, 1);
+ mark = pInfo->curr;
+ } else {
+ // Note that the original NSParser code was much more complex at this point, but it had to deal with 8-bit characters in a non-UniChar stream. We always have UniChar (we translated the data by the system encoding at the very beginning, hopefully), so this is safe.
+ pInfo->curr ++;
+ }
+ }
+ if (pInfo->end <= pInfo->curr) {
+ __CFPListRelease(str, pInfo->allocator);
+ pInfo->curr = startMark;
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unterminated quoted string starting on line %d"), lineNumberStrings(pInfo));
+ return NULL;
+ }
+ if (!str) {
+ if (pInfo->mutabilityOption == kCFPropertyListMutableContainersAndLeaves) {
+ str = CFStringCreateMutable(pInfo->allocator, 0);
+ CFStringAppendCharacters(str, mark, pInfo->curr - mark);
+ } else {
+ str = (CFMutableStringRef)_uniqueStringForCharacters(pInfo, mark, pInfo->curr-mark);
+ }
+ } else {
+ if (mark != pInfo->curr) {
+ CFStringAppendCharacters(str, mark, pInfo->curr - mark);
+ }
+ if (pInfo->mutabilityOption != kCFPropertyListMutableContainersAndLeaves) {
+ CFStringRef uniqueString = _uniqueStringForString(pInfo, str);
+ __CFPListRelease(str, pInfo->allocator);
+ str = (CFMutableStringRef)uniqueString;
+ }
+ }
+ pInfo->curr ++; // Advance past the quote character before returning.
+ if (pInfo->error) {
+ CFRelease(pInfo->error);
+ pInfo->error = NULL;
+ }
+ return str;
+}
+
+static CFStringRef parseUnquotedPlistString(_CFStringsFileParseInfo *pInfo) {
+ const UniChar *mark = pInfo->curr;
+ while (pInfo->curr < pInfo->end) {
+ UniChar ch = *pInfo->curr;
+ if (isValidUnquotedStringCharacter(ch))
+ pInfo->curr ++;
+ else break;
+ }
+ if (pInfo->curr != mark) {
+ if (pInfo->mutabilityOption != kCFPropertyListMutableContainersAndLeaves) {
+ CFStringRef str = _uniqueStringForCharacters(pInfo, mark, pInfo->curr-mark);
+ return str;
+ } else {
+ CFMutableStringRef str = CFStringCreateMutable(pInfo->allocator, 0);
+ CFStringAppendCharacters(str, mark, pInfo->curr - mark);
+ return str;
+ }
+ }
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unexpected EOF"));
+ return NULL;
+}
+
+static CFStringRef parsePlistString(_CFStringsFileParseInfo *pInfo, bool requireObject) {
+ UniChar ch;
+ Boolean foundChar = advanceToNonSpace(pInfo);
+ if (!foundChar) {
+ if (requireObject) {
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unexpected EOF while parsing string"));
+ }
+ return NULL;
+ }
+ ch = *(pInfo->curr);
+ if (ch == '\'' || ch == '\"') {
+ pInfo->curr ++;
+ return parseQuotedPlistString(pInfo, ch);
+ } else if (isValidUnquotedStringCharacter(ch)) {
+ return parseUnquotedPlistString(pInfo);
+ } else {
+ if (requireObject) {
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Invalid string character at line %d"), lineNumberStrings(pInfo));
+ }
+ return NULL;
+ }
+}
+
+static CFTypeRef parsePlistArray(_CFStringsFileParseInfo *pInfo) {
+ CFMutableArrayRef array = CFArrayCreateMutable(pInfo->allocator, 0, &kCFTypeArrayCallBacks);
+ CFTypeRef tmp = parsePlistObject(pInfo, false);
+ Boolean foundChar;
+ while (tmp) {
+ CFArrayAppendValue(array, tmp);
+ __CFPListRelease(tmp, pInfo->allocator);
+ foundChar = advanceToNonSpace(pInfo);
+ if (!foundChar) {
+ __CFPListRelease(array, pInfo->allocator);
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Expected ',' for array at line %d"), lineNumberStrings(pInfo));
+ return NULL;
+ }
+ if (*pInfo->curr != ',') {
+ tmp = NULL;
+ } else {
+ pInfo->curr ++;
+ tmp = parsePlistObject(pInfo, false);
+ }
+ }
+ foundChar = advanceToNonSpace(pInfo);
+ if (!foundChar || *pInfo->curr != ')') {
+ __CFPListRelease(array, pInfo->allocator);
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Expected terminating ')' for array at line %d"), lineNumberStrings(pInfo));
+ return NULL;
+ }
+ if (pInfo->error) {
+ CFRelease(pInfo->error);
+ pInfo->error = NULL;
+ }
+ pInfo->curr ++;
+ return array;
+}
+
+__attribute__((noinline)) void _CFPropertyListMissingSemicolon(UInt32 line) {
+ CFLog(kCFLogLevelWarning, CFSTR("CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary on line %d. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolon to debug."), line);
+}
+
+__attribute__((noinline)) void _CFPropertyListMissingSemicolonOrValue(UInt32 line) {
+ CFLog(kCFLogLevelWarning, CFSTR("CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon or value in dictionary on line %d. Parsing will be abandoned. Break on _CFPropertyListMissingSemicolonOrValue to debug."), line);
+}
+
+static CFDictionaryRef parsePlistDictContent(_CFStringsFileParseInfo *pInfo) {
+ CFMutableDictionaryRef dict = CFDictionaryCreateMutable(pInfo->allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFStringRef key = NULL;
+ Boolean failedParse = false;
+ key = parsePlistString(pInfo, false);
+ while (key) {
+ CFTypeRef value;
+ Boolean foundChar = advanceToNonSpace(pInfo);
+ if (!foundChar) {
+ UInt32 line = lineNumberStrings(pInfo);
+ _CFPropertyListMissingSemicolonOrValue(line);
+ failedParse = true;
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Missing ';' on line %d"), line);
+ break;
+ }
+
+ if (*pInfo->curr == ';') {
+ /* This is a strings file using the shortcut format */
+ /* although this check here really applies to all plists. */
+ value = CFRetain(key);
+ } else if (*pInfo->curr == '=') {
+ pInfo->curr ++;
+ value = parsePlistObject(pInfo, true);
+ if (!value) {
+ failedParse = true;
+ break;
+ }
+ } else {
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unexpected ';' or '=' after key at line %d"), lineNumberStrings(pInfo));
+ failedParse = true;
+ break;
+ }
+ CFDictionarySetValue(dict, key, value);
+ __CFPListRelease(key, pInfo->allocator);
+ key = NULL;
+ __CFPListRelease(value, pInfo->allocator);
+ value = NULL;
+ foundChar = advanceToNonSpace(pInfo);
+ if (foundChar && *pInfo->curr == ';') {
+ pInfo->curr ++;
+ key = parsePlistString(pInfo, false);
+ } else if (true || !foundChar) {
+ UInt32 line = lineNumberStrings(pInfo);
+ _CFPropertyListMissingSemicolon(line);
+ failedParse = true;
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Missing ';' on line %d"), line);
+ }
+ }
+
+ if (failedParse) {
+ __CFPListRelease(key, pInfo->allocator);
+ __CFPListRelease(dict, pInfo->allocator);
+ return NULL;
+ }
+ if (pInfo->error) {
+ CFRelease(pInfo->error);
+ pInfo->error = NULL;
+ }
+ return dict;
+}
+
+static CFTypeRef parsePlistDict(_CFStringsFileParseInfo *pInfo) {
+ CFDictionaryRef dict = parsePlistDictContent(pInfo);
+ if (!dict) return NULL;
+ Boolean foundChar = advanceToNonSpace(pInfo);
+ if (!foundChar || *pInfo->curr != '}') {
+ __CFPListRelease(dict, pInfo->allocator);
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Expected terminating '}' for dictionary at line %d"), lineNumberStrings(pInfo));
+ return NULL;
+ }
+ pInfo->curr ++;
+ return dict;
+}
+
+CF_INLINE unsigned char fromHexDigit(unsigned char ch) {
+ if (isdigit(ch)) return ch - '0';
+ if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10;
+ if ((ch >= 'A') && (ch <= 'F')) return ch - 'A' + 10;
+ return 0xff; // Just choose a large number for the error code
+}
+
+/* Gets up to bytesSize bytes from a plist data. Returns number of bytes actually read. Leaves cursor at first non-space, non-hex character.
+ -1 is returned for unexpected char, -2 for uneven number of hex digits
+ */
+static int getDataBytes(_CFStringsFileParseInfo *pInfo, unsigned char *bytes, int bytesSize) {
+ int numBytesRead = 0;
+ while ((pInfo->curr < pInfo->end) && (numBytesRead < bytesSize)) {
+ int first, second;
+ UniChar ch1 = *pInfo->curr;
+ if (ch1 == '>') return numBytesRead; // Meaning we're done
+ first = fromHexDigit((unsigned char)ch1);
+ if (first != 0xff) { // If the first char is a hex, then try to read a second hex
+ pInfo->curr++;
+ if (pInfo->curr >= pInfo->end) return -2; // Error: uneven number of hex digits
+ UniChar ch2 = *pInfo->curr;
+ second = fromHexDigit((unsigned char)ch2);
+ if (second == 0xff) return -2; // Error: uneven number of hex digits
+ bytes[numBytesRead++] = (first << 4) + second;
+ pInfo->curr++;
+ } else if (ch1 == ' ' || ch1 == '\n' || ch1 == '\t' || ch1 == '\r' || ch1 == 0x2028 || ch1 == 0x2029) {
+ pInfo->curr++;
+ } else {
+ return -1; // Error: unexpected character
+ }
+ }
+ return numBytesRead; // This does likely mean we didn't encounter a '>', but we'll let the caller deal with that
+}
+
+#define numBytes 400
+static CFTypeRef parsePlistData(_CFStringsFileParseInfo *pInfo) {
+ CFMutableDataRef result = CFDataCreateMutable(pInfo->allocator, 0);
+
+ // Read hex bytes and append them to result
+ while (1) {
+ unsigned char bytes[numBytes];
+ int numBytesRead = getDataBytes(pInfo, bytes, numBytes);
+ if (numBytesRead < 0) {
+ __CFPListRelease(result, pInfo->allocator);
+ switch (numBytesRead) {
+ case -2:
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Malformed data byte group at line %d; uneven length"), lineNumberStrings(pInfo));
+ break;
+ default:
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Malformed data byte group at line %d; invalid hex"), lineNumberStrings(pInfo));
+ break;
+ }
+ return NULL;
+ }
+ if (numBytesRead == 0) break;
+ CFDataAppendBytes(result, bytes, numBytesRead);
+ }
+
+ if (pInfo->error) {
+ CFRelease(pInfo->error);
+ pInfo->error = NULL;
+ }
+
+ if (*(pInfo->curr) == '>') {
+ pInfo->curr ++; // Move past '>'
+ return result;
+ } else {
+ __CFPListRelease(result, pInfo->allocator);
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Expected terminating '>' for data at line %d"), lineNumberStrings(pInfo));
+ return NULL;
+ }
+}
+#undef numBytes
+
+// Returned object is retained; caller must free.
+static CFTypeRef parsePlistObject(_CFStringsFileParseInfo *pInfo, bool requireObject) {
+ UniChar ch;
+ Boolean foundChar = advanceToNonSpace(pInfo);
+ if (!foundChar) {
+ if (requireObject) {
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unexpected EOF while parsing plist"));
+ }
+ return NULL;
+ }
+ ch = *(pInfo->curr);
+ pInfo->curr ++;
+ if (ch == '{') {
+ return parsePlistDict(pInfo);
+ } else if (ch == '(') {
+ return parsePlistArray(pInfo);
+ } else if (ch == '<') {
+ return parsePlistData(pInfo);
+ } else if (ch == '\'' || ch == '\"') {
+ return parseQuotedPlistString(pInfo, ch);
+ } else if (isValidUnquotedStringCharacter(ch)) {
+ pInfo->curr --;
+ return parseUnquotedPlistString(pInfo);
+ } else {
+ pInfo->curr --; // Must back off the charcter we just read
+ if (requireObject) {
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unexpected character '0x%x' at line %d"), ch, lineNumberStrings(pInfo));
+ }
+ return NULL;
+ }
+}
+
+// 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) {
+
+ // Convert the string to UTF16 for parsing old-style
+ if (originalString) {
+ // Ensure that originalString is not collected while we are using it
+ CFRetain(originalString);
+ } else {
+ originalString = CFStringCreateWithBytes(kCFAllocatorSystemDefault, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData), guessedEncoding, NO);
+ if (!originalString) {
+ // Couldn't convert
+ if (outError) *outError = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Conversion of string failed."));
+ return NULL;
+ }
+ }
+
+ UInt32 length;
+ Boolean createdBuffer = false;
+ length = CFStringGetLength(originalString);
+ if (!length) {
+ if (outError) *outError = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Conversion of string failed. The string is empty."));
+ return NULL;
+ }
+
+ UniChar *buf = (UniChar *)CFStringGetCharactersPtr(originalString);
+ if (!buf) {
+ buf = (UniChar *)CFAllocatorAllocate(allocator, length * sizeof(UniChar), 0);
+ if (!buf) {
+ CRSetCrashLogMessage("CFPropertyList ran out of memory while attempting to allocate temporary storage.");
+ return NULL;
+ }
+ CFStringGetCharacters(originalString, CFRangeMake(0, length), buf);
+ createdBuffer = true;
+ }
+
+ _CFStringsFileParseInfo stringsPInfo;
+ stringsPInfo.begin = buf;
+ stringsPInfo.end = buf+length;
+ stringsPInfo.curr = buf;
+ stringsPInfo.allocator = allocator;
+ stringsPInfo.mutabilityOption = option;
+ stringsPInfo.stringSet = CFSetCreateMutable(allocator, 0, &kCFTypeSetCallBacks);
+ stringsPInfo.error = NULL;
+
+ const UniChar *begin = stringsPInfo.curr;
+ CFTypeRef result = NULL;
+ Boolean foundChar = advanceToNonSpace(&stringsPInfo);
+ if (!foundChar) {
+ // A file consisting only of whitespace (or empty) is now defined to be an empty dictionary
+ result = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ } else {
+ result = parsePlistObject(&stringsPInfo, true);
+ if (result) {
+ foundChar = advanceToNonSpace(&stringsPInfo);
+ if (foundChar) {
+ if (CFGetTypeID(result) != CFStringGetTypeID()) {
+ __CFPListRelease(result, allocator);
+ result = NULL;
+ if (stringsPInfo.error) CFRelease(stringsPInfo.error);
+ stringsPInfo.error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Junk after plist at line %d"), lineNumberStrings(&stringsPInfo));
+ } else {
+ // Reset info and keep parsing
+ __CFPListRelease(result, allocator);
+ if (stringsPInfo.error) CFRelease(stringsPInfo.error);
+ stringsPInfo.error = NULL;
+
+ // Check for a strings file (looks like a dictionary without the opening/closing curly braces)
+ stringsPInfo.curr = begin;
+ result = parsePlistDictContent(&stringsPInfo);
+ }
+ }
+ }
+ }
+
+ if (!result) {
+ // Must return some kind of error if requested
+ if (outError) {
+ if (stringsPInfo.error) {
+ // Transfer ownership
+ *outError = stringsPInfo.error;
+ } else {
+ *outError = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unknown error parsing property list around line %d"), lineNumberStrings(&stringsPInfo));
+ }
+ } else if (stringsPInfo.error) {
+ // Caller doesn't want it, so we need to free it
+ CFRelease(stringsPInfo.error);
+ }
+ }
+
+ if (result && format) *format = kCFPropertyListOpenStepFormat;
+
+ if (createdBuffer && !_CFAllocatorIsGCRefZero(allocator)) CFAllocatorDeallocate(allocator, buf);
+ if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(stringsPInfo.stringSet);
+ CFRelease(originalString);
+ return result;
+}
+
+#undef isValidUnquotedStringCharacter
*/
/* CFPlatform.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Tony Parker
*/
#include "CFInternal.h"
#include <CoreFoundation/CFPriv.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS
#define kCFPlatformInterfaceStringEncoding kCFStringEncodingUTF8
#else
#define kCFPlatformInterfaceStringEncoding CFStringGetSystemEncoding()
#endif
-static CFStringRef _CFUserName(void);
+extern void __CFGetUGIDs(uid_t *euid, gid_t *egid);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
// CoreGraphics and LaunchServices are only projects (1 Dec 2006) that use these
char **_CFArgv(void) { return *_NSGetArgv(); }
int _CFArgc(void) { return *_NSGetArgc(); }
return getcwd(path, maxlen) != NULL;
}
-#if SUPPORT_CFM
-static Boolean __CFIsCFM = false;
-
-// If called super early, we just return false
-__private_extern__ Boolean _CFIsCFM(void) {
- return __CFIsCFM;
-}
-#endif
-
-#if DEPLOYMENT_TARGET_WINDOWS
-#define PATH_SEP '\\'
-#else
-#define PATH_SEP '/'
-#endif
-
-
#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;
}
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
const char *_CFProcessPath(void) {
if (__CFProcessPath) return __CFProcessPath;
#if DEPLOYMENT_TARGET_MACOSX
uint32_t size = CFMaxPathSize;
char buffer[size];
if (0 == _NSGetExecutablePath(buffer, &size)) {
-#if SUPPORT_CFM
- size_t len = strlen(buffer);
- if (12 <= len && 0 == strcmp("LaunchCFMApp", buffer + len - 12)) {
- struct stat exec, lcfm;
- const char *launchcfm = "/System/Library/Frameworks/Carbon.framework/Versions/Current/Support/LaunchCFMApp";
- if (0 == stat(launchcfm, &lcfm) && 0 == stat(buffer, &exec) && (lcfm.st_dev == exec.st_dev) && (lcfm.st_ino == exec.st_ino)) {
- // Executable is LaunchCFMApp, take special action
- __CFIsCFM = true;
- if ((*_NSGetArgv())[1] && '/' == *((*_NSGetArgv())[1])) {
- strlcpy(buffer, (*_NSGetArgv())[1], sizeof(buffer));
- }
- }
- }
-#endif
__CFProcessPath = strdup(buffer);
__CFprogname = strrchr(__CFProcessPath, PATH_SEP);
__CFprogname = (__CFprogname ? __CFprogname + 1 : __CFProcessPath);
return __CFProcessNameString;
}
-static CFStringRef __CFUserName = NULL;
-static CFSpinLock_t __CFPlatformCacheLock = CFSpinLockInit;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
#include <pwd.h>
+#include <sys/param.h>
-static CFURLRef __CFHomeDirectory = NULL;
-static uint32_t __CFEUID = -1;
-static uint32_t __CFUID = -1;
-
-static CFURLRef _CFCopyHomeDirURLForUser(struct passwd *upwd) { // __CFPlatformCacheLock must be locked on entry and will be on exit
+// Set the fallBackToHome parameter to true if we should fall back to the HOME environment variable if all else fails. Otherwise return NULL.
+static CFURLRef _CFCopyHomeDirURLForUser(struct passwd *upwd, bool fallBackToHome) {
+ const char *fixedHomePath = issetugid() ? NULL : __CFgetenv("CFFIXED_USER_HOME");
+ const char *homePath = NULL;
+
+ // Calculate the home directory we will use
+ // First try CFFIXED_USER_HOME (only if not setugid), then fall back to the upwd, then fall back to HOME environment variable
CFURLRef home = NULL;
- if (!issetugid()) {
- const char *path = __CFgetenv("CFFIXED_USER_HOME");
- if (path) {
- home = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, (uint8_t *)path, strlen(path), true);
- }
- }
- if (!home) {
- if (upwd && upwd->pw_dir) {
- home = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, (uint8_t *)upwd->pw_dir, strlen(upwd->pw_dir), true);
- }
- }
+ if (!issetugid() && fixedHomePath) home = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, (uint8_t *)fixedHomePath, strlen(fixedHomePath), true);
+ if (!home && upwd && upwd->pw_dir) home = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, (uint8_t *)upwd->pw_dir, strlen(upwd->pw_dir), true);
+ if (fallBackToHome && !home) homePath = __CFgetenv("HOME");
+ if (fallBackToHome && !home && homePath) home = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, (uint8_t *)homePath, strlen(homePath), true);
+
return home;
}
-static void _CFUpdateUserInfo(void) { // __CFPlatformCacheLock must be locked on entry and will be on exit
- struct passwd *upwd;
-
- __CFEUID = geteuid();
- __CFUID = getuid();
- if (__CFHomeDirectory) CFRelease(__CFHomeDirectory);
- __CFHomeDirectory = NULL;
- if (__CFUserName) CFRelease(__CFUserName);
- __CFUserName = NULL;
-
- upwd = getpwuid(__CFEUID ? __CFEUID : __CFUID);
- __CFHomeDirectory = _CFCopyHomeDirURLForUser(upwd);
- if (!__CFHomeDirectory) {
- const char *cpath = __CFgetenv("HOME");
- if (cpath) {
- __CFHomeDirectory = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, (uint8_t *)cpath, strlen(cpath), true);
- }
- }
+#endif
+
+
+#define CFMaxHostNameLength 256
+#define CFMaxHostNameSize (CFMaxHostNameLength+1)
+
+__private_extern__ CFStringRef _CFStringCreateHostName(void) {
+ char myName[CFMaxHostNameSize];
+
+ // return @"" instead of nil a la CFUserName() and Ali Ozer
+ if (0 != gethostname(myName, CFMaxHostNameSize)) myName[0] = '\0';
+ return CFStringCreateWithCString(kCFAllocatorSystemDefault, myName, kCFPlatformInterfaceStringEncoding);
+}
+
+/* These are sanitized versions of the above functions. We might want to eliminate the above ones someday.
+ These can return NULL.
+*/
+CF_EXPORT CFStringRef CFGetUserName(void) {
+ return CFCopyUserName();
+}
- // This implies that UserManager stores directory info in CString
- // rather than FileSystemRep. Perhaps this is wrong & we should
- // expect NeXTSTEP encodings. A great test of our localized system would
- // be to have a user "O-umlat z e r". XXX
+CF_EXPORT CFStringRef CFCopyUserName(void) {
+ CFStringRef result = NULL;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+ uid_t euid;
+ __CFGetUGIDs(&euid, NULL);
+ struct passwd *upwd = getpwuid(euid ? euid : getuid());
if (upwd && upwd->pw_name) {
- __CFUserName = CFStringCreateWithCString(kCFAllocatorSystemDefault, upwd->pw_name, kCFPlatformInterfaceStringEncoding);
+ result = CFStringCreateWithCString(kCFAllocatorSystemDefault, upwd->pw_name, kCFPlatformInterfaceStringEncoding);
} else {
const char *cuser = __CFgetenv("USER");
- if (cuser)
- __CFUserName = CFStringCreateWithCString(kCFAllocatorSystemDefault, cuser, kCFPlatformInterfaceStringEncoding);
+ if (cuser) {
+ result = CFStringCreateWithCString(kCFAllocatorSystemDefault, cuser, kCFPlatformInterfaceStringEncoding);
+ }
}
-}
+#elif DEPLOYMENT_TARGET_WINDOWS
+ wchar_t username[1040];
+ DWORD size = 1040;
+ username[0] = 0;
+ if (GetUserNameW(username, &size)) {
+ // discount the extra NULL by decrementing the size
+ result = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (const UniChar *)username, size - 1);
+ } else {
+ const char *cname = __CFgetenv("USERNAME");
+ if (cname) {
+ result = CFStringCreateWithCString(kCFAllocatorSystemDefault, cname, kCFPlatformInterfaceStringEncoding);
+ }
+ }
+#else
+#error Dont know how to compute user name on this platform
#endif
+ if (!result)
+ result = (CFStringRef)CFRetain(CFSTR(""));
+ return result;
+}
-static CFURLRef _CFCreateHomeDirectoryURLForUser(CFStringRef uName) { // __CFPlatformCacheLock must be locked on entry and will be on exit
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
- if (!uName) {
- if (geteuid() != __CFEUID || getuid() != __CFUID || !__CFHomeDirectory)
- _CFUpdateUserInfo();
- if (__CFHomeDirectory) CFRetain(__CFHomeDirectory);
- return __CFHomeDirectory;
- } else {
- struct passwd *upwd = NULL;
- char buf[128], *user;
- SInt32 len = CFStringGetLength(uName), size = CFStringGetMaximumSizeForEncoding(len, kCFPlatformInterfaceStringEncoding);
- CFIndex usedSize;
- if (size < 127) {
- user = buf;
- } else {
- user = CFAllocatorAllocate(kCFAllocatorSystemDefault, size+1, 0);
- if (__CFOASafe) __CFSetLastAllocationEventName(user, "CFUtilities (temp)");
- }
- if (CFStringGetBytes(uName, CFRangeMake(0, len), kCFPlatformInterfaceStringEncoding, 0, true, (uint8_t *)user, size, &usedSize) == len) {
- user[usedSize] = '\0';
- upwd = getpwnam(user);
- }
- if (buf != user) {
- CFAllocatorDeallocate(kCFAllocatorSystemDefault, user);
- }
- return _CFCopyHomeDirURLForUser(upwd);
- }
+CFURLRef CFCopyHomeDirectoryURL(void) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+ uid_t euid;
+ __CFGetUGIDs(&euid, NULL);
+ struct passwd *upwd = getpwuid(euid ? euid : getuid());
+ return _CFCopyHomeDirURLForUser(upwd, true);
#elif DEPLOYMENT_TARGET_WINDOWS
- // This code can only get the directory for the current user
- if (uName && !CFEqual(uName, _CFUserName())) {
- CFLog(kCFLogLevelError, CFSTR("CFCopyHomeDirectoryURLForUser(): Unable to get home directory for other user"));
- return NULL;
- }
-
CFURLRef retVal = NULL;
CFIndex len = 0;
CFStringRef str = NULL;
-
+
UniChar pathChars[MAX_PATH];
if (S_OK == SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, (wchar_t *)pathChars)) {
len = (CFIndex)wcslen((wchar_t *)pathChars);
retVal = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str, kCFURLWindowsPathStyle, true);
CFRelease(str);
}
-
+
if (!retVal) {
// Fall back to environment variable, but this will not be unicode compatible
const char *cpath = __CFgetenv("HOMEPATH");
CFRelease(str);
}
}
-
+
if (!retVal) {
// Last resort: We have to get "some" directory location, so fall-back to the processes current directory.
UniChar currDir[MAX_PATH];
CFRelease(str);
}
}
-
+
// We could do more here (as in KB Article Q101507). If that article is to be believed, we should only run into this case on Win95, or through user error.
CFStringRef testPath = CFURLCopyFileSystemPath(retVal, kCFURLWindowsPathStyle);
if (CFStringGetLength(testPath) == 0) {
retVal = NULL;
}
if (testPath) CFRelease(testPath);
-
+
return retVal;
#else
#error Dont know how to compute users home directories on this platform
#endif
}
-static CFStringRef _CFUserName(void) { // __CFPlatformCacheLock must be locked on entry and will be on exit
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
- if (geteuid() != __CFEUID || getuid() != __CFUID)
- _CFUpdateUserInfo();
+CF_EXPORT CFURLRef CFCopyHomeDirectoryURLForUser(CFStringRef uName) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+ if (!uName) {
+ uid_t euid;
+ __CFGetUGIDs(&euid, NULL);
+ struct passwd *upwd = getpwuid(euid ? euid : getuid());
+ return _CFCopyHomeDirURLForUser(upwd, true);
+ } else {
+ struct passwd *upwd = NULL;
+ char buf[128], *user;
+ SInt32 len = CFStringGetLength(uName), size = CFStringGetMaximumSizeForEncoding(len, kCFPlatformInterfaceStringEncoding);
+ CFIndex usedSize;
+ if (size < 127) {
+ user = buf;
+ } else {
+ user = CFAllocatorAllocate(kCFAllocatorSystemDefault, size+1, 0);
+ }
+ if (CFStringGetBytes(uName, CFRangeMake(0, len), kCFPlatformInterfaceStringEncoding, 0, true, (uint8_t *)user, size, &usedSize) == len) {
+ user[usedSize] = '\0';
+ upwd = getpwnam(user);
+ }
+ if (buf != user) {
+ CFAllocatorDeallocate(kCFAllocatorSystemDefault, user);
+ }
+ return _CFCopyHomeDirURLForUser(upwd, false);
+ }
#elif DEPLOYMENT_TARGET_WINDOWS
- if (!__CFUserName) {
- wchar_t username[1040];
- DWORD size = 1040;
- username[0] = 0;
- if (GetUserNameW(username, &size)) {
- // discount the extra NULL by decrementing the size
- __CFUserName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, (const UniChar *)username, size - 1);
- } else {
- const char *cname = __CFgetenv("USERNAME");
- if (cname)
- __CFUserName = CFStringCreateWithCString(kCFAllocatorSystemDefault, cname, kCFPlatformInterfaceStringEncoding);
- }
+ // This code can only get the directory for the current user
+ CFStringRef userName = uName ? CFCopyUserName() : NULL;
+ if (uName && !CFEqual(uName, userName)) {
+ CFLog(kCFLogLevelError, CFSTR("CFCopyHomeDirectoryURLForUser(): Unable to get home directory for other user"));
+ if (userName) CFRelease(userName);
+ return NULL;
}
+ if (userName) CFRelease(userName);
+ return CFCopyHomeDirectoryURL();
#else
-#error Dont know how to compute user name on this platform
+#error Dont know how to compute users home directories on this platform
#endif
- if (!__CFUserName)
- __CFUserName = (CFStringRef)CFRetain(CFSTR(""));
- return __CFUserName;
}
-#define CFMaxHostNameLength 256
-#define CFMaxHostNameSize (CFMaxHostNameLength+1)
-
-__private_extern__ CFStringRef _CFStringCreateHostName(void) {
- char myName[CFMaxHostNameSize];
-
- // return @"" instead of nil a la CFUserName() and Ali Ozer
- if (0 != gethostname(myName, CFMaxHostNameSize)) myName[0] = '\0';
- return CFStringCreateWithCString(kCFAllocatorSystemDefault, myName, kCFPlatformInterfaceStringEncoding);
-}
-
-/* These are sanitized versions of the above functions. We might want to eliminate the above ones someday.
- These can return NULL.
-*/
-CF_EXPORT CFStringRef CFGetUserName(void) {
- CFStringRef result = NULL;
- __CFSpinLock(&__CFPlatformCacheLock);
- result = CFStringCreateCopy(kCFAllocatorSystemDefault, _CFUserName());
- __CFSpinUnlock(&__CFPlatformCacheLock);
- return result;
-}
-
-CF_EXPORT CFStringRef CFCopyUserName(void) {
- CFStringRef result = NULL;
- __CFSpinLock(&__CFPlatformCacheLock);
- result = CFStringCreateCopy(kCFAllocatorSystemDefault, _CFUserName());
- __CFSpinUnlock(&__CFPlatformCacheLock);
- return result;
-}
-
-CF_EXPORT CFURLRef CFCopyHomeDirectoryURLForUser(CFStringRef uName) {
- CFURLRef result = NULL;
- __CFSpinLock(&__CFPlatformCacheLock);
- result = _CFCreateHomeDirectoryURLForUser(uName);
- __CFSpinUnlock(&__CFPlatformCacheLock);
- return result;
-}
#undef CFMaxHostNameLength
#undef CFMaxHostNameSize
// If thread data has been torn down, these functions should crash on CF_TSD_BAD_PTR + slot address.
#define CF_TSD_MAX_SLOTS 70
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#define CF_TSD_KEY 55
#endif
#endif
static void __CFTSDSetSpecific(void *arg) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
pthread_setspecific(CF_TSD_KEY, arg);
#elif DEPLOYMENT_TARGET_LINUX
pthread_setspecific(__CFTSDIndexKey, arg);
}
static void *__CFTSDGetSpecific() {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
return pthread_getspecific(CF_TSD_KEY);
#elif DEPLOYMENT_TARGET_LINUX
return pthread_getspecific(__CFTSDIndexKey);
}
static void __CFTSDFinalize(void *arg) {
- // Set our TSD so we're called again by pthreads. It will call the destructor 5 times as long as a value is set in the thread specific data. We handle each case below.
+ // Set our TSD so we're called again by pthreads. It will call the destructor PTHREAD_DESTRUCTOR_ITERATIONS times as long as a value is set in the thread specific data. We handle each case below.
__CFTSDSetSpecific(arg);
if (!arg || arg == CF_TSD_BAD_PTR) {
__CFTSDTable *table = (__CFTSDTable *)arg;
table->destructorCount++;
- // On 1st, 2nd, 3rd, 4th calls, invoke destructor
+ // On first calls invoke destructor. Later we destroy the data.
// Note that invocation of the destructor may cause a value to be set again in the per-thread data slots. The destructor count and destructors are preserved.
// This logic is basically the same as what pthreads does. We just skip the 'created' flag.
-#if COCOA_ARR0
- uintptr_t pool = _CFAutoreleasePoolPush();
-#endif
for (int32_t i = 0; i < CF_TSD_MAX_SLOTS; i++) {
if (table->data[i] && table->destructors[i]) {
uintptr_t old = table->data[i];
table->destructors[i]((void *)(old));
}
}
-#if COCOA_ARR0
- _CFAutoreleasePoolPop(pool);
-#endif
- if (table->destructorCount == PTHREAD_DESTRUCTOR_ITERATIONS - 1) { // On 4th call, destroy our data
+ if (table->destructorCount == PTHREAD_DESTRUCTOR_ITERATIONS - 1) { // On PTHREAD_DESTRUCTOR_ITERATIONS-1 call, destroy our data
free(table);
// Now if the destructor is called again we will take the shortcut at the beginning of this function.
}
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
extern int pthread_key_init_np(int, void (*)(void *));
#endif
// This memory is freed in the finalize function
table = (__CFTSDTable *)calloc(1, sizeof(__CFTSDTable));
// Windows and Linux have created the table already, we need to initialize it here for other platforms. On Windows, the cleanup function is called by DllMain when a thread exits. On Linux the destructor is set at init time.
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
pthread_key_init_np(CF_TSD_KEY, __CFTSDFinalize);
#endif
__CFTSDSetSpecific(table);
return oldVal;
}
+
#pragma mark -
#pragma mark Windows Wide to UTF8 and UTF8 to Wide
return fd;
}
-#endif
-#if DEPLOYMENT_TARGET_WINDOWS
// Utilities to convert from a volume name to a drive letter
Boolean _isAFloppy(char driveLetter)
return drivePathResult;
}
+struct timezone {
+ int tz_minuteswest; /* minutes west of Greenwich */
+ int tz_dsttime; /* type of dst correction */
+};
+
+__private_extern__ int _NS_gettimeofday(struct timeval *tv, struct timezone *tz) {
+ if (tv) {
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ unsigned __int64 t = 0;
+ t |= ft.dwHighDateTime;
+ t <<= 32;
+ t |= ft.dwLowDateTime;
+
+ // Convert to microseconds
+ t /= 10;
+
+ // Difference between 1/1/1970 and 1/1/1601
+ t -= 11644473600000000Ui64;
+
+ // Convert microseconds to seconds
+ tv->tv_sec = (long)(t / 1000000UL);
+ tv->tv_usec = (long)(t % 1000000UL);
+ }
+
+ // We don't support tz
+ return 0;
+}
+
#endif // DEPLOYMENT_TARGET_WINDOWS
#pragma mark -
}
#endif
+
*/
/* CFPlatformConverters.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Aki Inoue
*/
#include <CoreFoundation/CFString.h>
#include "CFStringEncodingConverterExt.h"
#include <CoreFoundation/CFStringEncodingExt.h>
-#include <CoreFoundation/CFPreferences.h>
#include "CFUniChar.h"
#include "CFUnicodeDecomposition.h"
#include "CFStringEncodingConverterPriv.h"
__private_extern__ const CFStringEncodingConverter *__CFStringEncodingGetExternalConverter(uint32_t encoding) {
- return (__CFIsPlatformConverterAvailable(encoding) ? &__CFPlatformBootstrap : (__CFStringEncodingGetICUName(encoding) ? &__CFICUBootstrap : NULL)); // we prefer Text Encoding Converter ICU since it's more reliable
+ // we prefer Text Encoding Converter ICU since it's more reliable
+ if (__CFIsPlatformConverterAvailable(encoding)) {
+ return &__CFPlatformBootstrap;
+ } else {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
+ if (__CFStringEncodingGetICUName(encoding)) {
+ return &__CFICUBootstrap;
+ }
+#endif
+ return NULL;
+ }
}
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
dwFlags |= (flags & (kCFStringEncodingUseCanonical|kCFStringEncodingUseHFSPlusCanonical) ? MB_COMPOSITE : MB_PRECOMPOSED);
}
- if ((usedLen = MultiByteToWideChar(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCSTR)bytes, numBytes, (LPWSTR)characters, maxCharLen) == 0)) {
+ if ((usedLen = MultiByteToWideChar(CFStringConvertEncodingToWindowsCodepage(encoding), dwFlags, (LPCSTR)bytes, numBytes, (LPWSTR)characters, maxCharLen)) == 0) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
CPINFO cpInfo;
*/
/* CFPlugIn.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
- Responsibility: David Smith
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
+ Responsibility: Tony Parker
*/
#include "CFBundle_Internal.h"
/* Functions for finding factories to create specific types and actually creating instances of a type. */
CF_EXPORT CFArrayRef CFPlugInFindFactoriesForPlugInType(CFUUIDRef typeID) {
- CFArrayRef array = _CFPFactoryFindForType(typeID);
+ CFArrayRef array = _CFPFactoryFindCopyForType(typeID);
CFMutableArrayRef result = NULL;
if (array) {
SInt32 i, c = CFArrayGetCount(array);
result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
- for (i = 0; i < c; i++) CFArrayAppendValue(result, _CFPFactoryGetFactoryID((_CFPFactory *)CFArrayGetValueAtIndex(array, i)));
+ for (i = 0; i < c; i++) {
+ CFUUIDRef factoryId = _CFPFactoryCopyFactoryID((_CFPFactoryRef)CFArrayGetValueAtIndex(array, i));
+ if (factoryId) {
+ CFArrayAppendValue(result, factoryId);
+ CFRelease(factoryId);
+ }
+ }
+ CFRelease(array);
}
return result;
}
CF_EXPORT CFArrayRef CFPlugInFindFactoriesForPlugInTypeInPlugIn(CFUUIDRef typeID, CFPlugInRef plugIn) {
- CFArrayRef array = _CFPFactoryFindForType(typeID);
+ CFArrayRef array = _CFPFactoryFindCopyForType(typeID);
CFMutableArrayRef result = NULL;
if (array) {
SInt32 i, c = CFArrayGetCount(array);
- _CFPFactory *factory;
+ _CFPFactoryRef factory;
result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
for (i = 0; i < c; i++) {
- factory = (_CFPFactory *)CFArrayGetValueAtIndex(array, i);
- if (_CFPFactoryGetPlugIn(factory) == plugIn) CFArrayAppendValue(result, _CFPFactoryGetFactoryID(factory));
+ factory = (_CFPFactoryRef )CFArrayGetValueAtIndex(array, i);
+ CFPlugInRef factoryPlugIn = _CFPFactoryCopyPlugIn(factory);
+ if (factoryPlugIn == plugIn) {
+ CFUUIDRef factoryId = _CFPFactoryCopyFactoryID(factory);
+ CFArrayAppendValue(result, factoryId);
+ CFRelease(factoryId);
+ }
+ if (factoryPlugIn) CFRelease(factoryPlugIn);
}
+ CFRelease(array);
}
return result;
}
CF_EXPORT void *CFPlugInInstanceCreate(CFAllocatorRef allocator, CFUUIDRef factoryID, CFUUIDRef typeID) {
- _CFPFactory *factory = _CFPFactoryFind(factoryID, true);
+ _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true);
void *result = NULL;
if (!factory) {
/* MF:!!! No such factory. */
CF_EXPORT Boolean CFPlugInRegisterFactoryFunction(CFUUIDRef factoryID, CFPlugInFactoryFunction func) {
// Create factories without plugIns from default allocator
// MF:!!! Should probably check that this worked, and maybe do some pre-checking to see if it already exists
- // _CFPFactory *factory =
+ // _CFPFactoryRef factory =
(void)_CFPFactoryCreate(kCFAllocatorSystemDefault, factoryID, func);
return true;
}
CF_EXPORT Boolean CFPlugInRegisterFactoryFunctionByName(CFUUIDRef factoryID, CFPlugInRef plugIn, CFStringRef functionName) {
// Create factories with plugIns from plugIn's allocator
// MF:!!! Should probably check that this worked, and maybe do some pre-checking to see if it already exists
- // _CFPFactory *factory =
+ // _CFPFactoryRef factory =
(void)_CFPFactoryCreateByName(CFGetAllocator(plugIn), factoryID, plugIn, functionName);
return true;
}
CF_EXPORT Boolean CFPlugInUnregisterFactory(CFUUIDRef factoryID) {
- _CFPFactory *factory = _CFPFactoryFind(factoryID, true);
+ _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true);
if (!factory) {
/* MF:!!! Error. No factory registered for this ID. */
}
CF_EXPORT Boolean CFPlugInRegisterPlugInType(CFUUIDRef factoryID, CFUUIDRef typeID) {
- _CFPFactory *factory = _CFPFactoryFind(factoryID, true);
+ _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true);
if (!factory) {
/* MF:!!! Error. Factory must be registered (and not disabled) before types can be associated with it. */
}
CF_EXPORT Boolean CFPlugInUnregisterPlugInType(CFUUIDRef factoryID, CFUUIDRef typeID) {
- _CFPFactory *factory = _CFPFactoryFind(factoryID, true);
+ _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true);
if (!factory) {
/* MF:!!! Error. Could not find factory. */
/* 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) {
- _CFPFactory *factory = _CFPFactoryFind(factoryID, true);
+ _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true);
if (!factory) {
/* MF:!!! Error. Could not find factory. */
}
CF_EXPORT void CFPlugInRemoveInstanceForFactory(CFUUIDRef factoryID) {
- _CFPFactory *factory = _CFPFactoryFind(factoryID, true);
+ _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true);
if (!factory) {
/* MF:!!! Error. Could not find factory. */
*/
/* CFPlugIn.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFPLUGIN__)
*/
/* CFPlugInCOM.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFPLUGINCOM__)
*/
/* CFPlugIn_Factory.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
- Responsibility: David Smith
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
+ Responsibility: Tony Parker
*/
#include "CFBundle_Internal.h"
#include "CFInternal.h"
-static CFSpinLock_t CFPlugInGlobalDataLock = CFSpinLockInit;
-static CFMutableDictionaryRef _factoriesByFactoryID = NULL; /* Value is _CFPFactory */
-static CFMutableDictionaryRef _factoriesByTypeID = NULL; /* Value is array of _CFPFactory */
+static CFTypeID __kCFPFactoryTypeID = _kCFRuntimeNotATypeID;
-static void _CFPFactoryAddToTable(_CFPFactory *factory) {
- __CFSpinLock(&CFPlugInGlobalDataLock);
+struct __CFPFactory {
+ CFRuntimeBase _base;
+
+ CFUUIDRef _uuid;
+ Boolean _enabled;
+ char _padding[3];
+
+ CFPlugInFactoryFunction _func;
+
+ CFPlugInRef _plugIn;
+ CFStringRef _funcName;
+
+ CFMutableArrayRef _types;
+ CFSpinLock_t _lock;
+};
+
+static void _CFPFactoryDeallocate(CFTypeRef factory);
+
+static const CFRuntimeClass __CFPFactoryClass = {
+ 0,
+ "_CFPFactory",
+ NULL, // init
+ NULL, // copy
+ _CFPFactoryDeallocate,
+ NULL, // equal
+ NULL, // hash
+ NULL, // formatting desc
+ NULL, // debug desc
+};
+
+__private_extern__ void __CFPFactoryInitialize(void) {
+ __kCFPFactoryTypeID = _CFRuntimeRegisterClass(&__CFPFactoryClass);
+}
+
+static CFTypeID _CFPFactoryGetTypeID(void) {
+ return __kCFPFactoryTypeID;
+}
+
+static CFSpinLock_t CFPlugInGlobalDataLock = CFSpinLockInit;
+static CFMutableDictionaryRef _factoriesByFactoryID = NULL; /* Value is _CFPFactoryRef */
+static CFMutableDictionaryRef _factoriesByTypeID = NULL; /* Value is array of _CFPFactoryRef */
+
+static void _CFPFactoryAddToTable(_CFPFactoryRef factory) {
+ __CFSpinLock(&factory->_lock);
+ CFUUIDRef uuid = (CFUUIDRef)CFRetain(factory->_uuid);
+ CFRetain(factory);
+ __CFSpinUnlock(&factory->_lock);
+
+ __CFSpinLock(&CFPlugInGlobalDataLock);
if (!_factoriesByFactoryID) {
CFDictionaryValueCallBacks _factoryDictValueCallbacks = {0, NULL, NULL, NULL, NULL};
_factoriesByFactoryID = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &_factoryDictValueCallbacks);
}
- CFDictionarySetValue(_factoriesByFactoryID, factory->_uuid, factory);
+ CFDictionarySetValue(_factoriesByFactoryID, uuid, factory);
__CFSpinUnlock(&CFPlugInGlobalDataLock);
+
+ if (uuid) CFRelease(uuid);
+ CFRelease(factory);
}
-static void _CFPFactoryRemoveFromTable(_CFPFactory *factory) {
+static void _CFPFactoryRemoveFromTable(_CFPFactoryRef factory) {
+ __CFSpinLock(&factory->_lock);
+ CFUUIDRef uuid = factory->_uuid;
+ if (uuid) CFRetain(uuid);
+ __CFSpinUnlock(&factory->_lock);
+
__CFSpinLock(&CFPlugInGlobalDataLock);
- if (_factoriesByFactoryID) CFDictionaryRemoveValue(_factoriesByFactoryID, factory->_uuid);
+ if (uuid && _factoriesByTypeID) CFDictionaryRemoveValue(_factoriesByFactoryID, uuid);
__CFSpinUnlock(&CFPlugInGlobalDataLock);
+
+ if (uuid) CFRelease(uuid);
}
-__private_extern__ _CFPFactory *_CFPFactoryFind(CFUUIDRef factoryID, Boolean enabled) {
- _CFPFactory *result = NULL;
+__private_extern__ _CFPFactoryRef _CFPFactoryFind(CFUUIDRef factoryID, Boolean enabled) {
+ _CFPFactoryRef result = NULL;
__CFSpinLock(&CFPlugInGlobalDataLock);
if (_factoriesByFactoryID) {
- result = (_CFPFactory *)CFDictionaryGetValue(_factoriesByFactoryID, factoryID);
+ result = (_CFPFactoryRef )CFDictionaryGetValue(_factoriesByFactoryID, factoryID);
if (result && result->_enabled != enabled) result = NULL;
}
__CFSpinUnlock(&CFPlugInGlobalDataLock);
return result;
}
-static void _CFPFactoryDeallocate(_CFPFactory *factory) {
- CFAllocatorRef allocator = factory->_allocator;
+static void _CFPFactoryDeallocate(CFTypeRef ty) {
SInt32 c;
+ _CFPFactoryRef factory = (_CFPFactoryRef)ty;
_CFPFactoryRemoveFromTable(factory);
- if (factory->_plugIn) _CFPlugInRemoveFactory(factory->_plugIn, factory);
-
+ if (factory->_plugIn) {
+ _CFPlugInRemoveFactory(factory->_plugIn, factory);
+ CFRelease(factory->_plugIn);
+ }
+
/* Remove all types for this factory. */
c = CFArrayGetCount(factory->_types);
while (c-- > 0) _CFPFactoryRemoveType(factory, (CFUUIDRef)CFArrayGetValueAtIndex(factory->_types, c));
if (factory->_funcName) CFRelease(factory->_funcName);
if (factory->_uuid) CFRelease(factory->_uuid);
-
- CFAllocatorDeallocate(allocator, factory);
- CFRelease(allocator);
}
-static _CFPFactory *_CFPFactoryCommonCreate(CFAllocatorRef allocator, CFUUIDRef factoryID) {
- _CFPFactory *factory;
- UInt32 size;
- size = sizeof(_CFPFactory);
- allocator = (allocator ? (CFAllocatorRef)CFRetain(allocator) : (CFAllocatorRef)CFRetain(__CFGetDefaultAllocator()));
- factory = (_CFPFactory *)CFAllocatorAllocate(allocator, size, 0);
- if (!factory) {
- CFRelease(allocator);
- return NULL;
- }
+static _CFPFactoryRef _CFPFactoryCommonCreate(CFAllocatorRef allocator, CFUUIDRef factoryID) {
+ _CFPFactoryRef factory;
+ uint32_t size;
+ size = sizeof(struct __CFPFactory) - sizeof(CFRuntimeBase);
+ factory = (_CFPFactoryRef)_CFRuntimeCreateInstance(allocator, _CFPFactoryGetTypeID(), size, NULL);
+ if (!factory) return NULL;
- factory->_allocator = allocator;
factory->_uuid = (CFUUIDRef)CFRetain(factoryID);
factory->_enabled = true;
- factory->_instanceCount = 0;
-
- _CFPFactoryAddToTable(factory);
-
factory->_types = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
+ factory->_lock = CFSpinLockInit; // WARNING: grab global lock before this lock
+
+ _CFPFactoryAddToTable(factory);
return factory;
}
-__private_extern__ _CFPFactory *_CFPFactoryCreate(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInFactoryFunction func) {
- _CFPFactory *factory = _CFPFactoryCommonCreate(allocator, factoryID);
+__private_extern__ _CFPFactoryRef _CFPFactoryCreate(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInFactoryFunction func) {
+ _CFPFactoryRef factory = _CFPFactoryCommonCreate(allocator, factoryID);
+ __CFSpinLock(&factory->_lock);
factory->_func = func;
factory->_plugIn = NULL;
factory->_funcName = NULL;
+ __CFSpinUnlock(&factory->_lock);
return factory;
}
-__private_extern__ _CFPFactory *_CFPFactoryCreateByName(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInRef plugIn, CFStringRef funcName) {
- _CFPFactory *factory = _CFPFactoryCommonCreate(allocator, factoryID);
+__private_extern__ _CFPFactoryRef _CFPFactoryCreateByName(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInRef plugIn, CFStringRef funcName) {
+ _CFPFactoryRef factory = _CFPFactoryCommonCreate(allocator, factoryID);
+ __CFSpinLock(&factory->_lock);
factory->_func = NULL;
- factory->_plugIn = plugIn;
+ factory->_plugIn = (CFPlugInRef)CFRetain(plugIn);
if (plugIn) _CFPlugInAddFactory(plugIn, factory);
factory->_funcName = (funcName ? (CFStringRef)CFStringCreateCopy(allocator, funcName) : NULL);
+ __CFSpinUnlock(&factory->_lock);
return factory;
}
-__private_extern__ CFUUIDRef _CFPFactoryGetFactoryID(_CFPFactory *factory) {
- return factory->_uuid;
+__private_extern__ CFUUIDRef _CFPFactoryCopyFactoryID(_CFPFactoryRef factory) {
+ __CFSpinLock(&factory->_lock);
+ CFUUIDRef uuid = factory->_uuid;
+ if (uuid) CFRetain(uuid);
+ __CFSpinUnlock(&factory->_lock);
+ return uuid;
}
-__private_extern__ CFPlugInRef _CFPFactoryGetPlugIn(_CFPFactory *factory) {
- return factory->_plugIn;
+__private_extern__ CFPlugInRef _CFPFactoryCopyPlugIn(_CFPFactoryRef factory) {
+ __CFSpinLock(&factory->_lock);
+ CFPlugInRef result = factory->_plugIn;
+ if (result) CFRetain(result);
+ __CFSpinUnlock(&factory->_lock);
+ return result;
}
-__private_extern__ void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CFPFactory *factory, CFUUIDRef typeID) {
+__private_extern__ void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CFPFactoryRef factory, CFUUIDRef typeID) {
void *result = NULL;
+
+ __CFSpinLock(&factory->_lock);
if (factory->_enabled) {
if (!factory->_func) {
factory->_func = (CFPlugInFactoryFunction)CFBundleGetFunctionPointerForName(factory->_plugIn, factory->_funcName);
}
if (factory->_func) {
// UPPGOOP
- FAULT_CALLBACK((void **)&(factory->_func));
- result = (void *)INVOKE_CALLBACK2(factory->_func, allocator, typeID);
+ CFPlugInFactoryFunction f = factory->_func;
+ __CFSpinUnlock(&factory->_lock);
+ FAULT_CALLBACK((void **)&(f));
+ result = (void *)INVOKE_CALLBACK2(f, allocator, typeID);
+ __CFSpinLock(&factory->_lock);
}
} else {
CFLog(__kCFLogPlugIn, CFSTR("Factory %@ is disabled"), factory->_uuid);
- }
+ }
+ __CFSpinUnlock(&factory->_lock);
+
return result;
}
-__private_extern__ void _CFPFactoryDisable(_CFPFactory *factory) {
+__private_extern__ void _CFPFactoryDisable(_CFPFactoryRef factory) {
+ __CFSpinLock(&factory->_lock);
factory->_enabled = false;
- if (factory->_instanceCount == 0) _CFPFactoryDeallocate(factory);
-}
-
-__private_extern__ Boolean _CFPFactoryIsEnabled(_CFPFactory *factory) {
- return factory->_enabled;
+ __CFSpinUnlock(&factory->_lock);
+ CFRelease(factory);
}
-__private_extern__ void _CFPFactoryFlushFunctionCache(_CFPFactory *factory) {
+__private_extern__ 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);
factory->_func = NULL;
+ __CFSpinUnlock(&factory->_lock);
}
-__private_extern__ void _CFPFactoryAddType(_CFPFactory *factory, CFUUIDRef typeID) {
- CFMutableArrayRef array;
-
+__private_extern__ 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 */
CFArrayAppendValue(factory->_types, typeID);
+ __CFSpinUnlock(&factory->_lock);
- /* Add the factory to the type's array of factories */
__CFSpinLock(&CFPlugInGlobalDataLock);
if (!_factoriesByTypeID) _factoriesByTypeID = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- array = (CFMutableArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
+ CFMutableArrayRef array = (CFMutableArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
if (!array) {
CFArrayCallBacks _factoryArrayCallbacks = {0, NULL, NULL, NULL, NULL};
// Create this from default allocator
__CFSpinUnlock(&CFPlugInGlobalDataLock);
}
-__private_extern__ void _CFPFactoryRemoveType(_CFPFactory *factory, CFUUIDRef typeID) {
+__private_extern__ void _CFPFactoryRemoveType(_CFPFactoryRef factory, CFUUIDRef typeID) {
/* Remove it from the factory's type list */
SInt32 idx;
+ __CFSpinLock(&factory->_lock);
idx = CFArrayGetFirstIndexOfValue(factory->_types, CFRangeMake(0, CFArrayGetCount(factory->_types)), typeID);
if (idx >= 0) CFArrayRemoveValueAtIndex(factory->_types, idx);
+ __CFSpinUnlock(&factory->_lock);
/* Remove the factory from the type's list of factories */
__CFSpinLock(&CFPlugInGlobalDataLock);
__CFSpinUnlock(&CFPlugInGlobalDataLock);
}
-__private_extern__ Boolean _CFPFactorySupportsType(_CFPFactory *factory, CFUUIDRef typeID) {
+__private_extern__ Boolean _CFPFactorySupportsType(_CFPFactoryRef factory, CFUUIDRef typeID) {
SInt32 idx;
+ __CFSpinLock(&factory->_lock);
idx = CFArrayGetFirstIndexOfValue(factory->_types, CFRangeMake(0, CFArrayGetCount(factory->_types)), typeID);
+ __CFSpinUnlock(&factory->_lock);
+
return (idx >= 0 ? true : false);
}
-__private_extern__ CFArrayRef _CFPFactoryFindForType(CFUUIDRef typeID) {
+__private_extern__ CFArrayRef _CFPFactoryFindCopyForType(CFUUIDRef typeID) {
CFArrayRef result = NULL;
-
__CFSpinLock(&CFPlugInGlobalDataLock);
- if (_factoriesByTypeID) result = (CFArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
+ if (_factoriesByTypeID) {
+ result = (CFArrayRef)CFDictionaryGetValue(_factoriesByTypeID, typeID);
+ if (result) CFRetain(result);
+ }
__CFSpinUnlock(&CFPlugInGlobalDataLock);
return result;
}
/* 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(_CFPFactory *factory) {
+__private_extern__ void _CFPFactoryAddInstance(_CFPFactoryRef factory) {
/* MF:!!! Assert that factory is enabled. */
- factory->_instanceCount++;
- if (factory->_plugIn) _CFPlugInAddPlugInInstance(factory->_plugIn);
+ CFRetain(factory);
+ __CFSpinLock(&factory->_lock);
+ CFPlugInRef plugin = factory->_plugIn;
+ if (plugin) CFRetain(plugin);
+ __CFSpinUnlock(&factory->_lock);
+ if (plugin) {
+ _CFPlugInAddPlugInInstance(plugin);
+ CFRelease(plugin);
+ }
}
-__private_extern__ void _CFPFactoryRemoveInstance(_CFPFactory *factory) {
- /* MF:!!! Assert that _instanceCount > 0. */
- factory->_instanceCount--;
- if (factory->_plugIn) _CFPlugInRemovePlugInInstance(factory->_plugIn);
- if (factory->_instanceCount == 0 && !factory->_enabled) _CFPFactoryDeallocate(factory);
+__private_extern__ void _CFPFactoryRemoveInstance(_CFPFactoryRef factory) {
+ __CFSpinLock(&factory->_lock);
+ CFPlugInRef plugin = factory->_plugIn;
+ if (plugin) CFRetain(plugin);
+ __CFSpinUnlock(&factory->_lock);
+ if (plugin) {
+ _CFPlugInRemovePlugInInstance(factory->_plugIn);
+ CFRelease(plugin);
+ }
+ CFRelease(factory);
}
*/
/* CFPlugIn_Factory.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFPLUGIN_FACTORY__)
CF_EXTERN_C_BEGIN
-typedef struct __CFPFactory {
- CFAllocatorRef _allocator;
+typedef struct __CFPFactory *_CFPFactoryRef;
- CFUUIDRef _uuid;
- Boolean _enabled;
- char _padding[3];
- SInt32 _instanceCount;
+extern _CFPFactoryRef _CFPFactoryCreate(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInFactoryFunction func);
+extern _CFPFactoryRef _CFPFactoryCreateByName(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInRef plugIn, CFStringRef funcName);
- CFPlugInFactoryFunction _func;
-
- CFPlugInRef _plugIn;
- CFStringRef _funcName;
+extern _CFPFactoryRef _CFPFactoryFind(CFUUIDRef factoryID, Boolean enabled);
- CFMutableArrayRef _types;
-} _CFPFactory;
+extern CFUUIDRef _CFPFactoryCopyFactoryID(_CFPFactoryRef factory);
+extern CFPlugInRef _CFPFactoryCopyPlugIn(_CFPFactoryRef factory);
-extern _CFPFactory *_CFPFactoryCreate(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInFactoryFunction func);
-extern _CFPFactory *_CFPFactoryCreateByName(CFAllocatorRef allocator, CFUUIDRef factoryID, CFPlugInRef plugIn, CFStringRef funcName);
+extern void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CFPFactoryRef factory, CFUUIDRef typeID);
+extern void _CFPFactoryDisable(_CFPFactoryRef factory);
-extern _CFPFactory *_CFPFactoryFind(CFUUIDRef factoryID, Boolean enabled);
+extern void _CFPFactoryFlushFunctionCache(_CFPFactoryRef factory);
-extern CFUUIDRef _CFPFactoryGetFactoryID(_CFPFactory *factory);
-extern CFPlugInRef _CFPFactoryGetPlugIn(_CFPFactory *factory);
+extern void _CFPFactoryAddType(_CFPFactoryRef factory, CFUUIDRef typeID);
+extern void _CFPFactoryRemoveType(_CFPFactoryRef factory, CFUUIDRef typeID);
-extern void *_CFPFactoryCreateInstance(CFAllocatorRef allocator, _CFPFactory *factory, CFUUIDRef typeID);
-extern void _CFPFactoryDisable(_CFPFactory *factory);
-extern Boolean _CFPFactoryIsEnabled(_CFPFactory *factory);
-
-extern void _CFPFactoryFlushFunctionCache(_CFPFactory *factory);
-
-extern void _CFPFactoryAddType(_CFPFactory *factory, CFUUIDRef typeID);
-extern void _CFPFactoryRemoveType(_CFPFactory *factory, CFUUIDRef typeID);
-
-extern Boolean _CFPFactorySupportsType(_CFPFactory *factory, CFUUIDRef typeID);
-extern CFArrayRef _CFPFactoryFindForType(CFUUIDRef typeID);
+extern Boolean _CFPFactorySupportsType(_CFPFactoryRef factory, CFUUIDRef typeID);
+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. */
-extern void _CFPFactoryAddInstance(_CFPFactory *factory);
-extern void _CFPFactoryRemoveInstance(_CFPFactory *factory);
+extern void _CFPFactoryAddInstance(_CFPFactoryRef factory);
+extern void _CFPFactoryRemoveInstance(_CFPFactoryRef factory);
CF_EXTERN_C_END
*/
/* CFPlugIn_Instance.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
- Responsibility: David Smith
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
+ Responsibility: Tony Parker
*/
#include "CFBundle_Internal.h"
struct __CFPlugInInstance {
CFRuntimeBase _base;
- _CFPFactory *factory;
+ _CFPFactoryRef factory;
CFPlugInInstanceGetInterfaceFunction getInterfaceFunction;
CFPlugInInstanceDeallocateInstanceDataFunction deallocateInstanceDataFunction;
}
CF_EXPORT CFStringRef CFPlugInInstanceGetFactoryName(CFPlugInInstanceRef instance) {
- return (CFStringRef)_CFPFactoryGetFactoryID(instance->factory);
+ // This function leaks, but it's the only safe way to access the factory name
+ CFUUIDRef factoryId = _CFPFactoryCopyFactoryID(instance->factory);
+ return (CFStringRef)factoryId;
}
CF_EXPORT void *CFPlugInInstanceGetInstanceData(CFPlugInInstanceRef instance) {
*/
/* CFPlugIn_PlugIn.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
- Responsibility: David Smith
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
+ Responsibility: Tony Parker
*/
#include "CFBundle_Internal.h"
/* Go through factories disabling them. Disabling these factories should cause them to dealloc since we wouldn't be deallocating if any of the factories had outstanding instances. So go backwards. */
c = CFArrayGetCount(__CFBundleGetPlugInData(bundle)->_factories);
- while (c-- > 0) _CFPFactoryDisable((_CFPFactory *)CFArrayGetValueAtIndex(__CFBundleGetPlugInData(bundle)->_factories, c));
+ while (c-- > 0) _CFPFactoryDisable((_CFPFactoryRef)CFArrayGetValueAtIndex(__CFBundleGetPlugInData(bundle)->_factories, c));
CFRelease(__CFBundleGetPlugInData(bundle)->_factories);
__CFBundleGetPlugInData(bundle)->_isPlugIn = false;
if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) {
SInt32 c = CFArrayGetCount(__CFBundleGetPlugInData(plugIn)->_factories);
/* First, flush all the function pointers that may be cached by our factories. */
- while (c-- > 0) _CFPFactoryFlushFunctionCache((_CFPFactory *)CFArrayGetValueAtIndex(__CFBundleGetPlugInData(plugIn)->_factories, c));
+ while (c-- > 0) _CFPFactoryFlushFunctionCache((_CFPFactoryRef)CFArrayGetValueAtIndex(__CFBundleGetPlugInData(plugIn)->_factories, c));
}
}
}
}
-__private_extern__ void _CFPlugInAddFactory(CFPlugInRef plugIn, _CFPFactory *factory) {
+__private_extern__ void _CFPlugInAddFactory(CFPlugInRef plugIn, _CFPFactoryRef factory) {
if (__CFBundleGetPlugInData(plugIn)->_isPlugIn) CFArrayAppendValue(__CFBundleGetPlugInData(plugIn)->_factories, factory);
}
-__private_extern__ void _CFPlugInRemoveFactory(CFPlugInRef plugIn, _CFPFactory *factory) {
+__private_extern__ 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);
*/
/* CFPreferences.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: David Smith
*/
*/
/* CFPreferences.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFPREFERENCES__)
*/
/* CFPriv.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
/*
#include <CoreFoundation/CFURL.h>
#include <CoreFoundation/CFLocale.h>
#include <CoreFoundation/CFDate.h>
+#include <CoreFoundation/CFSet.h>
#include <math.h>
CF_EXPORT const char **_CFGetProgname(void);
+#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_LINUX))
+CF_EXPORT void _CFRunLoopSetCurrent(CFRunLoopRef rl);
+#endif
+
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_LINUX)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
CF_EXPORT CFRunLoopRef CFRunLoopGetMain(void);
CF_EXPORT SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled);
-CF_EXPORT void _CFRunLoopSetCurrent(CFRunLoopRef rl);
CF_EXPORT void _CFRunLoopStopMode(CFRunLoopRef rl, CFStringRef modeName);
#endif
#endif
-enum {
+typedef CF_ENUM(CFIndex, CFURLComponentDecomposition) {
kCFURLComponentDecompositionNonHierarchical,
kCFURLComponentDecompositionRFC1808, /* use this for RFC 1738 decompositions as well */
kCFURLComponentDecompositionRFC2396
};
-typedef CFIndex CFURLComponentDecomposition;
typedef struct {
CFStringRef scheme;
directories!
??? On MacOS 8 this function currently returns an empty array.
*/
-enum {
+typedef CF_ENUM(CFIndex, CFSearchPathDirectory) {
kCFApplicationDirectory = 1, /* supported applications (Applications) */
kCFDemoApplicationDirectory, /* unsupported applications, demonstration versions (Demos) */
kCFDeveloperApplicationDirectory, /* developer applications (Developer/Applications) */
kCFUserDirectory, /* user home directories (Users) */
kCFDocumentationDirectory, /* documentation (Documentation) */
kCFDocumentDirectory, /* documents (Library/Documents) */
+
+ kCFCoreServiceDirectory = 10, // location of CoreServices directory (System/Library/CoreServices)
+ kCFAutosavedInformationDirectory = 11, // location of autosaved documents (Documents/Autosaved)
+ kCFDesktopDirectory = 12, // location of user's desktop
+ kCFCachesDirectory = 13, // location of discardable cache files (Library/Caches)
+ kCFApplicationSupportDirectory = 14, // location of application support files (plug-ins, etc) (Library/Application Support)
+ kCFDownloadsDirectory = 15, // location of the user's "Downloads" directory
+ kCFInputMethodsDirectory = 16, // input methods (Library/Input Methods)
+ kCFMoviesDirectory = 17, // location of user's Movies directory (~/Movies)
+ kCFMusicDirectory = 18, // location of user's Music directory (~/Music)
+ kCFPicturesDirectory = 19, // location of user's Pictures directory (~/Pictures)
+ kCFPrinterDescriptionDirectory = 20, // location of system's PPDs directory (Library/Printers/PPDs)
+ kCFSharedPublicDirectory = 21, // location of user's Public sharing directory (~/Public)
+ kCFPreferencePanesDirectory = 22, // location of the PreferencePanes directory for use with System Preferences (Library/PreferencePanes)
+
kCFAllApplicationsDirectory = 100, /* all directories where applications can occur (ie Applications, Demos, Administration, Developer/Applications) */
kCFAllLibrariesDirectory = 101 /* all directories where resources can occur (Library, Developer) */
};
-typedef CFIndex CFSearchPathDirectory;
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFSearchPathDomainMask) {
kCFUserDomainMask = 1, /* user's home directory --- place to install user's personal items (~) */
kCFLocalDomainMask = 2, /* local to the current machine --- place to install items available to everyone on this machine (/Local) */
kCFNetworkDomainMask = 4, /* publically available location in the local area network --- place to install items available on the network (/Network) */
kCFSystemDomainMask = 8, /* provided by Apple, unmodifiable (/System) */
kCFAllDomainsMask = 0x0ffff /* all domains: all of the above and more, future items */
};
-typedef CFOptionFlags CFSearchPathDomainMask;
CF_EXPORT
CFArrayRef CFCopySearchPathForDirectoriesInDomains(CFSearchPathDirectory directory, CFSearchPathDomainMask domainMask, Boolean expandTilde);
Note that for non-MACH this function always returns true.
*/
-enum {
+typedef CF_ENUM(CFIndex, CFSystemVersion) {
CFSystemVersionCheetah = 0, /* 10.0 */
CFSystemVersionPuma = 1, /* 10.1 */
CFSystemVersionJaguar = 2, /* 10.2 */
CFSystemVersionLeopard = 5, /* 10.5 */
CFSystemVersionSnowLeopard = 6, /* 10.6 */
CFSystemVersionLion = 7, /* 10.7 */
+ CFSystemVersionMountainLion = 8, /* 10.8 */
CFSystemVersionMax, /* This should bump up when new entries are added */
};
-typedef CFIndex CFSystemVersion;
CF_EXPORT Boolean _CFExecutableLinkedOnOrAfter(CFSystemVersion version);
-enum {
+typedef CF_ENUM(CFIndex, CFStringCharacterClusterType) {
kCFStringGraphemeCluster = 1, /* Unicode Grapheme Cluster */
kCFStringComposedCharacterCluster = 2, /* Compose all non-base (including spacing marks) */
kCFStringCursorMovementCluster = 3, /* Cluster suitable for cursor movements */
kCFStringBackwardDeletionCluster = 4 /* Cluster suitable for backward deletion */
};
-typedef CFIndex CFStringCharacterClusterType;
CF_EXPORT CFRange CFStringGetRangeOfCharacterClusterAtIndex(CFStringRef string, CFIndex charIndex, CFStringCharacterClusterType type);
return ts;
}
+// The 'filtered' function below is preferred to this older one
CF_EXPORT bool _CFPropertyListCreateSingleValue(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFStringRef keyPath, CFPropertyListRef *value, CFErrorRef *error);
+// 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);
+
+// 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
+} CF_ENUM_AVAILABLE(10_8, 6_0);
+
+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);
#if TARGET_OS_WIN32
#include <CoreFoundation/CFNotificationCenter.h>
CF_EXPORT CFArrayRef CFDateFormatterCreateDateFormatsFromTemplates(CFAllocatorRef allocator, CFArrayRef tmplates, CFOptionFlags options, CFLocaleRef locale);
+#if (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)
+// Available for internal use on embedded
+CF_EXPORT CFNotificationCenterRef CFNotificationCenterGetDistributedCenter(void);
+#endif
+
CF_EXTERN_C_END
*/
/* CFPropertyList.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Tony Parker
*/
#include <CoreFoundation/CFError_Private.h>
#include <CoreFoundation/CFPriv.h>
#include <CoreFoundation/CFStringEncodingConverter.h>
-#include <CoreFoundation/CFInternal.h>
+#include "CFInternal.h"
+#include <CoreFoundation/CFBurstTrie.h>
+#include <CoreFoundation/CFString.h>
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
#include <CoreFoundation/CFStream.h>
#endif
#define DOCTYPE_TAG_LENGTH 7
#define CDSECT_TAG_LENGTH 9
-#if DEPLOYMENT_TARGET_MACOSX
-// Set for some exceptional circumstances, like running out of memory
-extern char * __crashreporter_info__;
-
-#define out_of_memory_warning() \
- do { \
- __crashreporter_info__ = "CFPropertyList ran out of memory while attempting to allocate temporary storage."; \
- } while (0)
-#else
-#define out_of_memory_warning() do {} while (0)
-#endif
-
#if !defined(new_cftype_array)
#define new_cftype_array(N, C) \
size_t N ## _count__ = (C); \
if (N ## _count__ > LONG_MAX / sizeof(CFTypeRef)) { \
- out_of_memory_warning(); \
+ CRSetCrashLogMessage("CFPropertyList ran out of memory while attempting to allocate temporary storage."); \
HALT; \
} \
Boolean N ## _is_stack__ = (N ## _count__ <= 256); \
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); \
if (! N) { \
- out_of_memory_warning(); \
+ CRSetCrashLogMessage("CFPropertyList ran out of memory while attempting to allocate temporary storage."); \
HALT; \
} \
do {} while (0)
// Used to reference an old-style plist parser error inside of a more general XML error
#define CFPropertyListOldStyleParserErrorKey CFSTR("kCFPropertyListOldStyleParsingError")
-// don't allow _CFKeyedArchiverUID here
-#define __CFAssertIsPList(cf) CFAssert2(CFGetTypeID(cf) == CFStringGetTypeID() || CFGetTypeID(cf) == CFArrayGetTypeID() || CFGetTypeID(cf) == CFBooleanGetTypeID() || CFGetTypeID(cf) == CFNumberGetTypeID() || CFGetTypeID(cf) == CFDictionaryGetTypeID() || CFGetTypeID(cf) == CFDateGetTypeID() || CFGetTypeID(cf) == CFDataGetTypeID(), __kCFLogAssertion, "%s(): %p not of a property list type", __PRETTY_FUNCTION__, cf);
-
-static bool __CFPropertyListIsValidAux(CFPropertyListRef plist, bool recursive, CFMutableSetRef set, CFPropertyListFormat format, CFStringRef *error);
-
-static CFTypeID stringtype = -1, datatype = -1, numbertype = -1, datetype = -1;
-static CFTypeID booltype = -1, nulltype = -1, dicttype = -1, arraytype = -1, settype = -1;
+static CFTypeID stringtype, datatype, numbertype, datetype;
+static CFTypeID booltype, nulltype, dicttype, arraytype, settype;
static void initStatics() {
- if ((CFTypeID)-1 == stringtype) {
+ static dispatch_once_t once;
+ dispatch_once(&once, ^{
stringtype = CFStringGetTypeID();
- }
- if ((CFTypeID)-1 == datatype) {
- datatype = CFDataGetTypeID();
- }
- if ((CFTypeID)-1 == numbertype) {
+ datatype = CFDataGetTypeID();
numbertype = CFNumberGetTypeID();
- }
- if ((CFTypeID)-1 == booltype) {
booltype = CFBooleanGetTypeID();
- }
- if ((CFTypeID)-1 == datetype) {
datetype = CFDateGetTypeID();
- }
- if ((CFTypeID)-1 == dicttype) {
dicttype = CFDictionaryGetTypeID();
- }
- if ((CFTypeID)-1 == arraytype) {
arraytype = CFArrayGetTypeID();
- }
- if ((CFTypeID)-1 == settype) {
settype = CFSetGetTypeID();
- }
- if ((CFTypeID)-1 == nulltype) {
nulltype = CFNullGetTypeID();
- }
+ });
}
__private_extern__ CFErrorRef __CFPropertyListCreateError(CFIndex code, CFStringRef debugString, ...) {
return error;
}
-CFStringRef __CFPropertyListCopyErrorDebugDescription(CFErrorRef error) {
+static CFStringRef __copyErrorDebugDescription(CFErrorRef error) {
CFStringRef result = NULL;
if (error) {
CFDictionaryRef userInfo = CFErrorCopyUserInfo(error);
return result;
}
+#pragma mark -
+#pragma mark Property List Validation
+
+// don't allow _CFKeyedArchiverUID here
+#define __CFAssertIsPList(cf) CFAssert2(CFGetTypeID(cf) == CFStringGetTypeID() || CFGetTypeID(cf) == CFArrayGetTypeID() || CFGetTypeID(cf) == CFBooleanGetTypeID() || CFGetTypeID(cf) == CFNumberGetTypeID() || CFGetTypeID(cf) == CFDictionaryGetTypeID() || CFGetTypeID(cf) == CFDateGetTypeID() || CFGetTypeID(cf) == CFDataGetTypeID(), __kCFLogAssertion, "%s(): %p not of a property list type", __PRETTY_FUNCTION__, cf);
struct context {
bool answer;
CFStringRef *error;
};
+static bool __CFPropertyListIsValidAux(CFPropertyListRef plist, bool recursive, CFMutableSetRef set, CFPropertyListFormat format, CFStringRef *error);
+
static void __CFPropertyListIsArrayPlistAux(const void *value, void *context) {
struct context *ctx = (struct context *)context;
if (!ctx->answer) return;
return false;
}
-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);
- CFStringRef error = NULL;
- bool result = __CFPropertyListIsValidAux(plist, true, set, format, &error);
- if (error) {
-#if defined(DEBUG)
- CFLog(kCFLogLevelWarning, CFSTR("CFPropertyListIsValid(): %@"), error);
-#endif
- CFRelease(error);
- }
- if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(set);
- return result;
-}
-
static Boolean _CFPropertyListIsValidWithErrorString(CFPropertyListRef plist, CFPropertyListFormat format, CFStringRef *error) {
initStatics();
CFAssert1(plist != NULL, __kCFLogAssertion, "%s(): NULL is not a property list", __PRETTY_FUNCTION__);
return result;
}
-static const UniChar CFXMLPlistTags[13][10]= {
+#pragma mark -
+#pragma mark Writing Property Lists
+
+static const char CFXMLPlistTags[13][10]= {
{'p', 'l', 'i', 's', 't', '\0', '\0', '\0', '\0', '\0'},
{'a', 'r', 'r', 'a', 'y', '\0', '\0', '\0', '\0', '\0'},
{'d', 'i', 'c', 't', '\0', '\0', '\0', '\0', '\0', '\0'},
{'<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[', '\0'}
};
+static const UniChar CFXMLPlistTagsUnicode[13][10]= {
+ {'p', 'l', 'i', 's', 't', '\0', '\0', '\0', '\0', '\0'},
+ {'a', 'r', 'r', 'a', 'y', '\0', '\0', '\0', '\0', '\0'},
+ {'d', 'i', 'c', 't', '\0', '\0', '\0', '\0', '\0', '\0'},
+ {'k', 'e', 'y', '\0', '\0', '\0', '\0', '\0', '\0', '\0'},
+ {'s', 't', 'r', 'i', 'n', 'g', '\0', '\0', '\0', '\0'},
+ {'d', 'a', 't', 'a', '\0', '\0', '\0', '\0', '\0', '\0'},
+ {'d', 'a', 't', 'e', '\0', '\0', '\0', '\0', '\0', '\0'},
+ {'r', 'e', 'a', 'l', '\0', '\0', '\0', '\0', '\0', '\0'},
+ {'i', 'n', 't', 'e', 'g', 'e', 'r', '\0', '\0', '\0'},
+ {'t', 'r', 'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0'},
+ {'f', 'a', 'l', 's', 'e', '\0', '\0', '\0', '\0', '\0'},
+ {'D', 'O', 'C', 'T', 'Y', 'P', 'E', '\0', '\0', '\0'},
+ {'<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[', '\0'}
+};
+
typedef struct {
- const UniChar *begin; // first character of the XML to be parsed
- const UniChar *curr; // current parse location
- const UniChar *end; // the first character _after_ the end of the XML
+ const char *begin; // first character of the XML to be parsed
+ const char *curr; // current parse location
+ const char *end; // the first character _after_ the end of the XML
CFErrorRef error;
CFAllocatorRef allocator;
UInt32 mutabilityOption;
- CFMutableSetRef stringSet; // set of all strings involved in this parse; allows us to share non-mutable strings in the returned plist
+ CFBurstTrieRef stringTrie; // map of cached strings
+ CFMutableArrayRef stringCache; // retaining array of strings
Boolean allowNewTypes; // Whether to allow the new types supported by XML property lists, but not by the old, OPENSTEP ASCII property lists (CFNumber, CFBoolean, CFDate)
- char _padding[3];
+ CFSetRef keyPaths; // if NULL, no filtering
+ Boolean skip; // if true, do not create any objects.
} _CFXMLPlistParseInfo;
-static CFTypeRef parseOldStylePropertyListOrStringsFile(_CFXMLPlistParseInfo *pInfo);
+__private_extern__ CFTypeRef __CFParseOldStylePropertyListOrStringsFile(CFAllocatorRef allocator, CFDataRef xmlData, CFStringRef originalString, CFStringEncoding guessedEncoding, CFOptionFlags option, CFErrorRef *outError,CFPropertyListFormat *format);
-CF_INLINE void __CFPListRelease(CFTypeRef cf, _CFXMLPlistParseInfo *pInfo) {
- if (cf && !_CFAllocatorIsGCRefZero(pInfo->allocator)) CFRelease(cf);
+CF_INLINE void __CFPListRelease(CFTypeRef cf, CFAllocatorRef allocator) {
+ if (cf && !_CFAllocatorIsGCRefZero(allocator)) CFRelease(cf);
}
_appendIndents(indentation, xmlString);
if (typeID == stringtype) {
_plistAppendUTF8CString(xmlString, "<");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[STRING_IX], STRING_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[STRING_IX], STRING_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">");
_appendEscapedString((CFStringRef)object, xmlString);
_plistAppendUTF8CString(xmlString, "</");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[STRING_IX], STRING_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[STRING_IX], STRING_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">\n");
} else if (typeID == arraytype) {
UInt32 i, count = CFArrayGetCount((CFArrayRef)object);
if (count == 0) {
_plistAppendUTF8CString(xmlString, "<");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[ARRAY_IX], ARRAY_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[ARRAY_IX], ARRAY_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, "/>\n");
return;
}
_plistAppendUTF8CString(xmlString, "<");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[ARRAY_IX], ARRAY_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[ARRAY_IX], ARRAY_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">\n");
for (i = 0; i < count; i ++) {
_CFAppendXML0(CFArrayGetValueAtIndex((CFArrayRef)object, i), indentation+1, xmlString);
}
_appendIndents(indentation, xmlString);
_plistAppendUTF8CString(xmlString, "</");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[ARRAY_IX], ARRAY_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[ARRAY_IX], ARRAY_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">\n");
} else if (typeID == dicttype) {
UInt32 i, count = CFDictionaryGetCount((CFDictionaryRef)object);
CFMutableArrayRef keyArray;
if (count == 0) {
_plistAppendUTF8CString(xmlString, "<");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[DICT_IX], DICT_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[DICT_IX], DICT_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, "/>\n");
return;
}
_plistAppendUTF8CString(xmlString, "<");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[DICT_IX], DICT_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[DICT_IX], DICT_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">\n");
new_cftype_array(keys, count);
CFDictionaryGetKeysAndValues((CFDictionaryRef)object, keys, NULL);
CFTypeRef key = keys[i];
_appendIndents(indentation+1, xmlString);
_plistAppendUTF8CString(xmlString, "<");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[KEY_IX], KEY_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[KEY_IX], KEY_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">");
_appendEscapedString((CFStringRef)key, xmlString);
_plistAppendUTF8CString(xmlString, "</");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[KEY_IX], KEY_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[KEY_IX], KEY_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">\n");
_CFAppendXML0(CFDictionaryGetValue((CFDictionaryRef)object, key), indentation+1, xmlString);
}
free_cftype_array(keys);
_appendIndents(indentation, xmlString);
_plistAppendUTF8CString(xmlString, "</");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[DICT_IX], DICT_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[DICT_IX], DICT_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">\n");
} else if (typeID == datatype) {
_plistAppendUTF8CString(xmlString, "<");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[DATA_IX], DATA_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[DATA_IX], DATA_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">\n");
_XMLPlistAppendDataUsingBase64(xmlString, (CFDataRef)object, indentation);
_appendIndents(indentation, xmlString);
_plistAppendUTF8CString(xmlString, "</");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[DATA_IX], DATA_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[DATA_IX], DATA_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">\n");
} else if (typeID == datetype) {
// YYYY '-' MM '-' DD 'T' hh ':' mm ':' ss 'Z'
CFRelease(tz);
#endif
_plistAppendUTF8CString(xmlString, "<");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[DATE_IX], DATE_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[DATE_IX], DATE_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">");
_plistAppendFormat(xmlString, CFSTR("%04d-%02d-%02dT%02d:%02d:%02dZ"), y, M, d, H, m, s);
_plistAppendUTF8CString(xmlString, "</");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[DATE_IX], DATE_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[DATE_IX], DATE_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">\n");
} else if (typeID == numbertype) {
if (CFNumberIsFloatType((CFNumberRef)object)) {
_plistAppendUTF8CString(xmlString, "<");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[REAL_IX], REAL_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">");
CFStringRef s = __CFNumberCopyFormattingDescriptionAsFloat64(object);
_plistAppendString(xmlString, s);
CFRelease(s);
_plistAppendUTF8CString(xmlString, "</");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[REAL_IX], REAL_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">\n");
} else {
_plistAppendUTF8CString(xmlString, "<");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[INTEGER_IX], INTEGER_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[INTEGER_IX], INTEGER_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">");
_plistAppendFormat(xmlString, CFSTR("%@"), object);
_plistAppendUTF8CString(xmlString, "</");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[INTEGER_IX], INTEGER_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[INTEGER_IX], INTEGER_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, ">\n");
}
} else if (typeID == booltype) {
if (CFBooleanGetValue((CFBooleanRef)object)) {
_plistAppendUTF8CString(xmlString, "<");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[TRUE_IX], TRUE_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[TRUE_IX], TRUE_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, "/>\n");
} else {
_plistAppendUTF8CString(xmlString, "<");
- _plistAppendCharacters(xmlString, CFXMLPlistTags[FALSE_IX], FALSE_TAG_LENGTH);
+ _plistAppendCharacters(xmlString, CFXMLPlistTagsUnicode[FALSE_IX], FALSE_TAG_LENGTH);
_plistAppendUTF8CString(xmlString, "/>\n");
}
}
static void _CFGenerateXMLPropertyListToData(CFMutableDataRef xml, CFTypeRef propertyList) {
_plistAppendUTF8CString(xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE ");
- _plistAppendCharacters(xml, CFXMLPlistTags[PLIST_IX], PLIST_TAG_LENGTH);
+ _plistAppendCharacters(xml, CFXMLPlistTagsUnicode[PLIST_IX], PLIST_TAG_LENGTH);
_plistAppendUTF8CString(xml, " PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<");
- _plistAppendCharacters(xml, CFXMLPlistTags[PLIST_IX], PLIST_TAG_LENGTH);
+ _plistAppendCharacters(xml, CFXMLPlistTagsUnicode[PLIST_IX], PLIST_TAG_LENGTH);
_plistAppendUTF8CString(xml, " version=\"1.0\">\n");
_CFAppendXML0(propertyList, 0, xml);
_plistAppendUTF8CString(xml, "</");
- _plistAppendCharacters(xml, CFXMLPlistTags[PLIST_IX], PLIST_TAG_LENGTH);
+ _plistAppendCharacters(xml, CFXMLPlistTagsUnicode[PLIST_IX], PLIST_TAG_LENGTH);
_plistAppendUTF8CString(xml, ">\n");
}
+// ========================================================================
+#pragma mark -
+#pragma mark Exported Creation Functions
+
CFDataRef _CFPropertyListCreateXMLData(CFAllocatorRef allocator, CFPropertyListRef propertyList, Boolean checkValidPlist) {
initStatics();
CFMutableDataRef xml;
return _CFPropertyListCreateXMLData(allocator, propertyList, false);
}
+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);
+ CFStringRef error = NULL;
+ bool result = __CFPropertyListIsValidAux(plist, true, set, format, &error);
+ if (error) {
+#if defined(DEBUG)
+ CFLog(kCFLogLevelWarning, CFSTR("CFPropertyListIsValid(): %@"), error);
+#endif
+ CFRelease(error);
+ }
+ if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(set);
+ return result;
+}
+
// ========================================================================
+#pragma mark -
+#pragma mark Reading Plists
//
// ------------------------- Reading plists ------------------
//
static void skipInlineDTD(_CFXMLPlistParseInfo *pInfo);
-static CFTypeRef parseXMLElement(_CFXMLPlistParseInfo *pInfo, Boolean *isKey);
+static Boolean parseXMLElement(_CFXMLPlistParseInfo *pInfo, Boolean *isKey, CFTypeRef *out);
// warning: doesn't have a good idea of Unicode line separators
static UInt32 lineNumber(_CFXMLPlistParseInfo *pInfo) {
- const UniChar *p = pInfo->begin;
+ const char *p = pInfo->begin;
UInt32 count = 1;
while (p < pInfo->curr) {
if (*p == '\r') {
// pInfo should be just past "<!--"
static void skipXMLComment(_CFXMLPlistParseInfo *pInfo) {
- const UniChar *p = pInfo->curr;
- const UniChar *end = pInfo->end - 3; // Need at least 3 characters to compare against
+ const char *p = pInfo->curr;
+ const char *end = pInfo->end - 3; // Need at least 3 characters to compare against
while (p < end) {
if (*p == '-' && *(p+1) == '-' && *(p+2) == '>') {
pInfo->curr = p+3;
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unterminated comment started on line %d"), lineNumber(pInfo));
}
-// stringToMatch and buf must both be of at least len
-static Boolean matchString(const UniChar *buf, const UniChar *stringToMatch, UInt32 len) {
- switch (len) {
- case 10: if (buf[9] != stringToMatch[9]) return false;
- case 9: if (buf[8] != stringToMatch[8]) return false;
- case 8: if (buf[7] != stringToMatch[7]) return false;
- case 7: if (buf[6] != stringToMatch[6]) return false;
- case 6: if (buf[5] != stringToMatch[5]) return false;
- case 5: if (buf[4] != stringToMatch[4]) return false;
- case 4: if (buf[3] != stringToMatch[3]) return false;
- case 3: if (buf[2] != stringToMatch[2]) return false;
- case 2: if (buf[1] != stringToMatch[1]) return false;
- case 1: if (buf[0] != stringToMatch[0]) return false;
- case 0: return true;
- }
- return false; // internal error
-}
-
// pInfo should be set to the first character after "<?"
static void skipXMLProcessingInstruction(_CFXMLPlistParseInfo *pInfo) {
- const UniChar *begin = pInfo->curr, *end = pInfo->end - 2; // Looking for "?>" so we need at least 2 characters
+ const char *begin = pInfo->curr, *end = pInfo->end - 2; // Looking for "?>" so we need at least 2 characters
while (pInfo->curr < end) {
if (*(pInfo->curr) == '?' && *(pInfo->curr+1) == '>') {
pInfo->curr += 2;
// first character should be immediately after the "<!"
static void skipDTD(_CFXMLPlistParseInfo *pInfo) {
// First pass "DOCTYPE"
- if (pInfo->end - pInfo->curr < DOCTYPE_TAG_LENGTH || !matchString(pInfo->curr, CFXMLPlistTags[DOCTYPE_IX], DOCTYPE_TAG_LENGTH)) {
+ if (pInfo->end - pInfo->curr < DOCTYPE_TAG_LENGTH || memcmp(pInfo->curr, CFXMLPlistTags[DOCTYPE_IX], DOCTYPE_TAG_LENGTH)) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Malformed DTD on line %d"), lineNumber(pInfo));
return;
}
// Look for either the beginning of a complex DTD or the end of the DOCTYPE structure
while (pInfo->curr < pInfo->end) {
- UniChar ch = *(pInfo->curr);
+ char ch = *(pInfo->curr);
if (ch == '[') break; // inline DTD
if (ch == '>') { // End of the DTD
pInfo->curr ++;
}
static void skipPERef(_CFXMLPlistParseInfo *pInfo) {
- const UniChar *p = pInfo->curr;
+ const char *p = pInfo->curr;
while (p < pInfo->end) {
if (*p == ';') {
pInfo->curr = p+1;
}
}
-/* A bit wasteful to do everything with unichars (since we know all the characters we're going to see are 7-bit ASCII), but since our data is coming from or going to a CFString, this prevents the extra cost of converting formats. */
-
-static const signed char __CFPLDataDecodeTable[128] = {
- /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1,
- /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1,
- /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1,
- /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1,
- /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1,
- /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63,
- /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59,
- /* '8' */ 60, 61, -1, -1, -1, 0, -1, -1,
- /* '@' */ -1, 0, 1, 2, 3, 4, 5, 6,
- /* 'H' */ 7, 8, 9, 10, 11, 12, 13, 14,
- /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22,
- /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1,
- /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32,
- /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40,
- /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48,
- /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1
-};
-
-static CFDataRef __CFPLDataDecode(_CFXMLPlistParseInfo *pInfo, Boolean isMutable) {
- int tmpbufpos = 0;
- int tmpbuflen = 256;
- uint8_t *tmpbuf;
- int numeq = 0;
- int acc = 0;
- int cntr = 0;
-
- tmpbuf = (uint8_t *)CFAllocatorAllocate(pInfo->allocator, tmpbuflen, 0);
- for (; pInfo->curr < pInfo->end; pInfo->curr++) {
- UniChar c = *(pInfo->curr);
- if (c == '<') {
- break;
- }
- if ('=' == c) {
- numeq++;
- } else if (!isspace(c)) {
- numeq = 0;
- }
- if (__CFPLDataDecodeTable[c] < 0)
- continue;
- cntr++;
- acc <<= 6;
- acc += __CFPLDataDecodeTable[c];
- if (0 == (cntr & 0x3)) {
- if (tmpbuflen <= tmpbufpos + 2) {
- if (tmpbuflen < 256 * 1024) {
- tmpbuflen *= 4;
- } else if (tmpbuflen < 16 * 1024 * 1024) {
- tmpbuflen *= 2;
- } else {
- // once in this stage, this will be really slow
- // and really potentially fragment memory
- tmpbuflen += 256 * 1024;
- }
- tmpbuf = (uint8_t *)CFAllocatorReallocate(pInfo->allocator, tmpbuf, tmpbuflen, 0);
- if (!tmpbuf) HALT;
- }
- tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff;
- if (numeq < 2)
- tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff;
- if (numeq < 1)
- tmpbuf[tmpbufpos++] = acc & 0xff;
- }
- }
- if (isMutable) {
- CFMutableDataRef result = CFDataCreateMutable(pInfo->allocator, 0);
- CFDataAppendBytes(result, tmpbuf, tmpbufpos);
- CFAllocatorDeallocate(pInfo->allocator, tmpbuf);
- return result;
- } else {
- return CFDataCreateWithBytesNoCopy(pInfo->allocator, tmpbuf, tmpbufpos, pInfo->allocator);
- }
-}
-
// content ::== (element | CharData | Reference | CDSect | PI | Comment)*
// In the context of a plist, CharData, Reference and CDSect are not legal (they all resolve to strings). Skipping whitespace, then, the next character should be '<'. From there, we figure out which of the three remaining cases we have (element, PI, or Comment).
-static CFTypeRef getContentObject(_CFXMLPlistParseInfo *pInfo, Boolean *isKey) {
+static Boolean getContentObject(_CFXMLPlistParseInfo *pInfo, Boolean *isKey, CFTypeRef *out) {
if (isKey) *isKey = false;
while (!pInfo->error && pInfo->curr < pInfo->end) {
skipWhitespace(pInfo);
if (pInfo->curr >= pInfo->end) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
- return NULL;
+ return false;
}
if (*(pInfo->curr) != '<') {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c on line %d"), *(pInfo->curr), lineNumber(pInfo));
- return NULL;
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c on line %d while looking for open tag"), *(pInfo->curr), lineNumber(pInfo));
+ return false;
}
pInfo->curr ++;
if (pInfo->curr >= pInfo->end) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
- return NULL;
+ return false;
}
switch (*(pInfo->curr)) {
case '?':
// Could be a comment
if (pInfo->curr+2 >= pInfo->end) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
- return NULL;
+ return false;
}
if (*(pInfo->curr+1) == '-' && *(pInfo->curr+2) == '-') {
pInfo->curr += 2;
skipXMLComment(pInfo);
} else {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
- return NULL;
+ return false;
}
break;
case '/':
// Whoops! Looks like we got to the end tag for the element whose content we're parsing
pInfo->curr --; // Back off to the '<'
- return NULL;
+ return false;
default:
// Should be an element
- return parseXMLElement(pInfo, isKey);
+ return parseXMLElement(pInfo, isKey, out);
}
}
// Do not set the error string here; if it wasn't already set by one of the recursive parsing calls, the caller will quickly detect the failure (b/c pInfo->curr >= pInfo->end) and provide a more useful one of the form "end tag for <blah> not found"
- return NULL;
-}
-
-static void _catFromMarkToBuf(const UniChar *mark, const UniChar *buf, CFMutableStringRef *string, _CFXMLPlistParseInfo *pInfo) {
- if (!(*string)) {
- *string = CFStringCreateMutable(pInfo->allocator, 0);
- }
- CFStringAppendCharacters(*string, mark, buf-mark);
+ return false;
}
-static void parseCDSect_pl(_CFXMLPlistParseInfo *pInfo, CFMutableStringRef string) {
- const UniChar *end, *begin;
+static void parseCDSect_pl(_CFXMLPlistParseInfo *pInfo, CFMutableDataRef stringData) {
+ const char *end, *begin;
if (pInfo->end - pInfo->curr < CDSECT_TAG_LENGTH) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
return;
}
- if (!matchString(pInfo->curr, CFXMLPlistTags[CDSECT_IX], CDSECT_TAG_LENGTH)) {
+ if (memcmp(pInfo->curr, CFXMLPlistTags[CDSECT_IX], CDSECT_TAG_LENGTH)) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered improper CDATA opening at line %d"), lineNumber(pInfo));
return;
}
end = pInfo->end-2; // So we can safely look 2 characters beyond p
while (pInfo->curr < end) {
if (*(pInfo->curr) == ']' && *(pInfo->curr+1) == ']' && *(pInfo->curr+2) == '>') {
- // Found the end!
- CFStringAppendCharacters(string, begin, pInfo->curr-begin);
+ // Found the end!
+ CFDataAppendBytes(stringData, (const UInt8 *)begin, pInfo->curr-begin);
pInfo->curr += 3;
return;
}
}
// Only legal references are {lt, gt, amp, apos, quote, #ddd, #xAAA}
-static void parseEntityReference_pl(_CFXMLPlistParseInfo *pInfo, CFMutableStringRef string) {
+static void parseEntityReference_pl(_CFXMLPlistParseInfo *pInfo, CFMutableDataRef stringData) {
int len;
- UniChar ch;
pInfo->curr ++; // move past the '&';
- len = pInfo->end - pInfo->curr; // how many characters we can safely scan
+ len = pInfo->end - pInfo->curr; // how many bytes we can safely scan
if (len < 1) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
return;
}
+
+ char ch;
switch (*(pInfo->curr)) {
case 'l': // "lt"
if (len >= 3 && *(pInfo->curr+1) == 't' && *(pInfo->curr+2) == ';') {
ch = *(pInfo->curr);
pInfo->curr ++;
if (ch == ';') {
- CFStringAppendCharacters(string, &num, 1);
+ // The value in num always refers to the unicode code point. We'll have to convert since the calling function expects UTF8 data.
+ CFStringRef oneChar = CFStringCreateWithBytes(pInfo->allocator, (const uint8_t *)&num, 2, kCFStringEncodingUnicode, NO);
+ uint8_t tmpBuf[6]; // max of 6 bytes for UTF8
+ CFIndex tmpBufLength = 0;
+ CFStringGetBytes(oneChar, CFRangeMake(0, 1), kCFStringEncodingUTF8, 0, NO, tmpBuf, 6, &tmpBufLength);
+ CFDataAppendBytes(stringData, tmpBuf, tmpBufLength);
+ __CFPListRelease(oneChar, pInfo->allocator);
return;
}
if (!isHex) num = num*10;
if (ch <= '9' && ch >= '0') {
num += (ch - '0');
} else if (!isHex) {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c at line %d"), ch, lineNumber(pInfo));
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c at line %d while parsing data"), ch, lineNumber(pInfo));
return;
} else if (ch >= 'a' && ch <= 'f') {
num += 10 + (ch - 'a');
} else if (ch >= 'A' && ch <= 'F') {
num += 10 + (ch - 'A');
} else {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c at line %d"), ch, lineNumber(pInfo));
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c at line %d while parsing data"), ch, lineNumber(pInfo));
return;
}
}
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unknown ampersand-escape sequence at line %d"), lineNumber(pInfo));
return;
}
- CFStringAppendCharacters(string, &ch, 1);
+ CFDataAppendBytes(stringData, (const UInt8 *)&ch, 1);
}
extern void _CFStrSetDesiredCapacity(CFMutableStringRef str, CFIndex len);
-static CFStringRef _uniqueStringForString(_CFXMLPlistParseInfo *pInfo, CFStringRef stringToUnique) {
- CFStringRef uniqued = (CFStringRef)CFSetGetValue(pInfo->stringSet, stringToUnique);
- if (!uniqued) {
- uniqued = (CFStringRef)__CFStringCollectionCopy(pInfo->allocator, stringToUnique);
- CFSetAddValue(pInfo->stringSet, uniqued);
- __CFTypeCollectionRelease(pInfo->allocator, uniqued);
- }
- if (uniqued && !_CFAllocatorIsGCRefZero(pInfo->allocator)) CFRetain(uniqued);
- return uniqued;
-}
-
-static CFStringRef _uniqueStringForCharacters(_CFXMLPlistParseInfo *pInfo, const UniChar *base, CFIndex length) {
- if (0 == length) return !_CFAllocatorIsGCRefZero(pInfo->allocator) ? (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;
- Boolean use_stack = (length < 2048);
- STACK_BUFFER_DECL(uint8_t, buffer, use_stack ? length + 1 : 1);
- uint8_t *ascii = use_stack ? buffer : (uint8_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, length + 1, 0);
- for (CFIndex idx = 0; idx < length; idx++) {
- UniChar ch = base[idx];
- if (ch < 0x80) {
- ascii[idx] = (uint8_t)ch;
- } else {
- stringToUnique = CFStringCreateWithCharacters(pInfo->allocator, base, length);
- break;
- }
- }
- if (!stringToUnique) {
- ascii[length] = '\0';
- stringToUnique = CFStringCreateWithBytes(pInfo->allocator, ascii, length, kCFStringEncodingASCII, false);
- }
- if (ascii != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, ascii);
- CFStringRef uniqued = (CFStringRef)CFSetGetValue(pInfo->stringSet, stringToUnique);
- if (!uniqued) {
- CFSetAddValue(pInfo->stringSet, stringToUnique);
- uniqued = stringToUnique;
+static void _createStringMap(_CFXMLPlistParseInfo *pInfo) {
+ pInfo->stringTrie = CFBurstTrieCreate();
+ pInfo->stringCache = CFArrayCreateMutable(pInfo->allocator, 0, &kCFTypeArrayCallBacks);
+}
+
+static void _cleanupStringMap(_CFXMLPlistParseInfo *pInfo) {
+ CFBurstTrieRelease(pInfo->stringTrie);
+ if (!_CFAllocatorIsGCRefZero(pInfo->allocator)) CFRelease(pInfo->stringCache);
+}
+
+static CFStringRef _uniqueStringForUTF8Bytes(_CFXMLPlistParseInfo *pInfo, const char *base, CFIndex length) {
+ if (length == 0) return !_CFAllocatorIsGCRefZero(pInfo->allocator) ? (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);
+ } 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);
}
- __CFPListRelease(stringToUnique, pInfo);
- if (uniqued && !_CFAllocatorIsGCRefZero(pInfo->allocator)) CFRetain(uniqued);
- return uniqued;
+ return result;
}
// String could be comprised of characters, CDSects, or references to one of the "well-known" entities ('<', '>', '&', ''', '"')
-// returns a retained object in *string.
-static CFStringRef getString(_CFXMLPlistParseInfo *pInfo) {
- const UniChar *mark = pInfo->curr; // At any time in the while loop below, the characters between mark and p have not yet been added to *string
- CFMutableStringRef string = NULL;
+static Boolean parseStringTag(_CFXMLPlistParseInfo *pInfo, CFStringRef *out) {
+ const char *mark = pInfo->curr;
+ CFMutableDataRef stringData = NULL;
while (!pInfo->error && pInfo->curr < pInfo->end) {
- UniChar ch = *(pInfo->curr);
+ char ch = *(pInfo->curr);
if (ch == '<') {
if (pInfo->curr + 1 >= pInfo->end) break;
// Could be a CDSect; could be the end of the string
if (*(pInfo->curr+1) != '!') break; // End of the string
- _catFromMarkToBuf(mark, pInfo->curr, &string, pInfo);
- parseCDSect_pl(pInfo, string);
+ if (!stringData) stringData = CFDataCreateMutable(pInfo->allocator, 0);
+ CFDataAppendBytes(stringData, (const UInt8 *)mark, pInfo->curr - mark);
+ parseCDSect_pl(pInfo, stringData); // TODO: move to return boolean
mark = pInfo->curr;
} else if (ch == '&') {
- _catFromMarkToBuf(mark, pInfo->curr, &string, pInfo);
- parseEntityReference_pl(pInfo, string);
+ if (!stringData) stringData = CFDataCreateMutable(pInfo->allocator, 0);
+ CFDataAppendBytes(stringData, (const UInt8 *)mark, pInfo->curr - mark);
+ parseEntityReference_pl(pInfo, stringData); // TODO: move to return boolean
mark = pInfo->curr;
} else {
pInfo->curr ++;
}
if (pInfo->error) {
- __CFPListRelease(string, pInfo);
- return NULL;
+ __CFPListRelease(stringData, pInfo->allocator);
+ return false;
}
- if (!string) {
- if (pInfo->mutabilityOption != kCFPropertyListMutableContainersAndLeaves) {
- CFStringRef uniqueString = _uniqueStringForCharacters(pInfo, mark, pInfo->curr-mark);
- return uniqueString;
+
+ if (!stringData) {
+ if (pInfo->skip) {
+ *out = NULL;
} else {
- string = CFStringCreateMutable(pInfo->allocator, 0);
- CFStringAppendCharacters(string, mark, pInfo->curr - mark);
- return string;
+ if (pInfo->mutabilityOption != kCFPropertyListMutableContainersAndLeaves) {
+ CFStringRef s = _uniqueStringForUTF8Bytes(pInfo, mark, pInfo->curr - mark);
+ if (!s) {
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unable to convert string to correct encoding"));
+ return false;
+ }
+ *out = s;
+ } else {
+ CFStringRef s = CFStringCreateWithBytes(pInfo->allocator, (const UInt8 *)mark, pInfo->curr - mark, kCFStringEncodingUTF8, NO);
+ if (!s) {
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unable to convert string to correct encoding"));
+ return false;
+ }
+ *out = CFStringCreateMutableCopy(pInfo->allocator, 0, s);
+ __CFPListRelease(s, pInfo->allocator);
+ }
}
+ return true;
+ } else {
+ if (pInfo->skip) {
+ *out = NULL;
+ } else {
+ CFDataAppendBytes(stringData, (const UInt8 *)mark, pInfo->curr - mark);
+ if (pInfo->mutabilityOption != kCFPropertyListMutableContainersAndLeaves) {
+ CFStringRef s = _uniqueStringForUTF8Bytes(pInfo, (const char *)CFDataGetBytePtr(stringData), CFDataGetLength(stringData));
+ if (!s) {
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unable to convert string to correct encoding"));
+ return false;
+ }
+ *out = s;
+ } else {
+ CFStringRef s = CFStringCreateWithBytes(pInfo->allocator, (const UInt8 *)CFDataGetBytePtr(stringData), CFDataGetLength(stringData), kCFStringEncodingUTF8, NO);
+ if (!s) {
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unable to convert string to correct encoding"));
+ return false;
+ }
+ *out = CFStringCreateMutableCopy(pInfo->allocator, 0, s);
+ __CFPListRelease(s, pInfo->allocator);
+ }
+ }
+ __CFPListRelease(stringData, pInfo->allocator);
+ return true;
}
- _catFromMarkToBuf(mark, pInfo->curr, &string, pInfo);
- if (pInfo->mutabilityOption != kCFPropertyListMutableContainersAndLeaves) {
- CFStringRef uniqueString = _uniqueStringForString(pInfo, string);
- __CFPListRelease(string, pInfo);
- return uniqueString;
- }
- return string;
}
-static Boolean checkForCloseTag(_CFXMLPlistParseInfo *pInfo, const UniChar *tag, CFIndex tagLen) {
+static Boolean checkForCloseTag(_CFXMLPlistParseInfo *pInfo, const char *tag, CFIndex tagLen) {
if (pInfo->end - pInfo->curr < tagLen + 3) {
if (!pInfo->error) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
}
if (*(pInfo->curr) != '<' || *(++pInfo->curr) != '/') {
if (!pInfo->error) {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c on line %d"), *(pInfo->curr), lineNumber(pInfo));
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c on line %d while looking for close tag"), *(pInfo->curr), lineNumber(pInfo));
}
return false;
}
pInfo->curr ++;
- if (!matchString(pInfo->curr, tag, tagLen)) {
- CFStringRef str = CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault, tag, tagLen, kCFAllocatorNull);
+ if (memcmp(pInfo->curr, tag, tagLen)) {
+ CFStringRef str = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (const UInt8 *)tag, tagLen, kCFStringEncodingUTF8, NO);
if (!pInfo->error) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Close tag on line %d does not match open tag %@"), lineNumber(pInfo), str);
}
}
if (*(pInfo->curr) != '>') {
if (!pInfo->error) {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c on line %d"), *(pInfo->curr), lineNumber(pInfo));
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected character %c on line %d while looking for close tag"), *(pInfo->curr), lineNumber(pInfo));
}
return false;
}
}
// pInfo should be set to the first content character of the <plist>
-static CFTypeRef parsePListTag(_CFXMLPlistParseInfo *pInfo) {
- CFTypeRef result, tmp = NULL;
- const UniChar *save;
- result = getContentObject(pInfo, NULL);
- if (!result) {
+static Boolean parsePListTag(_CFXMLPlistParseInfo *pInfo, CFTypeRef *out) {
+ CFTypeRef result = NULL;
+ if (!getContentObject(pInfo, NULL, &result)) {
if (!pInfo->error) pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered empty plist tag"));
- return NULL;
+ return false;
}
- save = pInfo->curr; // Save this in case the next step fails
- tmp = getContentObject(pInfo, NULL);
- if (tmp) {
+ const char *save = pInfo->curr; // Save this in case the next step fails
+ CFTypeRef tmp = NULL;
+ if (getContentObject(pInfo, NULL, &tmp)) {
// Got an extra object
- __CFPListRelease(tmp, pInfo);
- __CFPListRelease(result, pInfo);
+ __CFPListRelease(tmp, pInfo->allocator);
+ __CFPListRelease(result, pInfo->allocator);
pInfo->curr = save;
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected element at line %d (plist can only include one object)"), lineNumber(pInfo));
- return NULL;
+ return false;
}
if (pInfo->error) {
// Parse failed catastrophically
- __CFPListRelease(result, pInfo);
- return NULL;
+ __CFPListRelease(result, pInfo->allocator);
+ return false;
}
- if (checkForCloseTag(pInfo, CFXMLPlistTags[PLIST_IX], PLIST_TAG_LENGTH)) {
- return result;
+ if (!checkForCloseTag(pInfo, CFXMLPlistTags[PLIST_IX], PLIST_TAG_LENGTH)) {
+ __CFPListRelease(result, pInfo->allocator);
+ return false;
}
- __CFPListRelease(result, pInfo);
- return NULL;
+ *out = result;
+ return true;
}
static int allowImmutableCollections = -1;
allowImmutableCollections = (NULL == __CFgetenv("CFPropertyListAllowImmutableCollections")) ? 0 : 1;
}
-static CFTypeRef parseArrayTag(_CFXMLPlistParseInfo *pInfo) {
+// This converts the input value, a set of strings, into the form that's efficient for using during recursive decent parsing, a set of arrays
+static CFSetRef createTopLevelKeypaths(CFAllocatorRef allocator, CFSetRef keyPaths) {
+ if (!keyPaths) return NULL;
+
+ CFIndex count = CFSetGetCount(keyPaths);
+ new_cftype_array(keyPathValues, count);
+ CFSetGetValues(keyPaths, keyPathValues);
+ CFMutableSetRef splitKeyPathSet = CFSetCreateMutable(allocator, count, &kCFTypeSetCallBacks);
+ for (CFIndex i = 0; i < count; i++) {
+ // Split each key path and add it to the split path set, which we will reference throughout parsing
+ CFArrayRef split = CFStringCreateArrayBySeparatingStrings(allocator, (CFStringRef)(keyPathValues[i]), CFSTR(":"));
+ CFSetAddValue(splitKeyPathSet, split);
+ __CFPListRelease(split, allocator);
+ }
+ free_cftype_array(keyPathValues);
+ return splitKeyPathSet;
+}
+
+// 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) {
+ if (!currentKeys) { *theseKeys = NULL; *nextKeys = NULL; return; }
+
+ CFIndex count = CFSetGetCount(currentKeys);
+
+ // For each array in the current key path set, grab the item at the start of the list and put it into theseKeys. The rest of the array goes into nextKeys.
+ CFMutableSetRef outTheseKeys = NULL;
+ CFMutableSetRef outNextKeys = NULL;
+
+ new_cftype_array(currentKeyPaths, count);
+ CFSetGetValues(currentKeys, currentKeyPaths);
+ for (CFIndex i = 0; i < count; i++) {
+ CFArrayRef oneKeyPath = (CFArrayRef)currentKeyPaths[i];
+ CFIndex keyPathCount = CFArrayGetCount(oneKeyPath);
+
+ if (keyPathCount > 0) {
+ if (!outTheseKeys) outTheseKeys = CFSetCreateMutable(allocator, 0, &kCFTypeSetCallBacks);
+
+ CFSetAddValue(outTheseKeys, CFArrayGetValueAtIndex(oneKeyPath, 0));
+ }
+
+ if (keyPathCount > 1) {
+ if (!outNextKeys) outNextKeys = CFSetCreateMutable(allocator, 0, &kCFTypeSetCallBacks);
+
+ // Create an array with values from 1 - end of list
+ new_cftype_array(restOfKeys, keyPathCount - 1);
+ CFArrayGetValues(oneKeyPath, CFRangeMake(1, CFArrayGetCount(oneKeyPath) - 1), restOfKeys);
+ CFArrayRef newNextKeys = CFArrayCreate(allocator, restOfKeys, CFArrayGetCount(oneKeyPath) - 1, &kCFTypeArrayCallBacks);
+ CFSetAddValue(outNextKeys, newNextKeys);
+ __CFPListRelease(newNextKeys, allocator);
+ free_cftype_array(restOfKeys);
+
+ }
+ }
+
+ *theseKeys = outTheseKeys;
+ *nextKeys = outNextKeys;
+}
+
+static Boolean parseArrayTag(_CFXMLPlistParseInfo *pInfo, CFTypeRef *out) {
+ CFTypeRef tmp = NULL;
+
+ if (pInfo->skip) {
+ Boolean result = getContentObject(pInfo, NULL, &tmp);
+ while (result) {
+ if (tmp) {
+ // Shouldn't happen (if skipping, all content values should be null), but just in case
+ __CFPListRelease(tmp, pInfo->allocator);
+ }
+ result = getContentObject(pInfo, NULL, &tmp);
+ }
+
+ if (pInfo->error) {
+ // getContentObject encountered a parse error
+ return false;
+ }
+ if (!checkForCloseTag(pInfo, CFXMLPlistTags[ARRAY_IX], ARRAY_TAG_LENGTH)) {
+ return false;
+ } else {
+ *out = NULL;
+ return true;
+ }
+ }
+
CFMutableArrayRef array = CFArrayCreateMutable(pInfo->allocator, 0, &kCFTypeArrayCallBacks);
- CFTypeRef tmp = getContentObject(pInfo, NULL);
- while (tmp) {
- CFArrayAppendValue(array, tmp);
- __CFPListRelease(tmp, pInfo);
- tmp = getContentObject(pInfo, NULL);
+ Boolean result;
+
+ CFIndex count = 0;
+ CFSetRef oldKeyPaths = pInfo->keyPaths;
+ CFSetRef newKeyPaths, keys;
+ __CFPropertyListCreateSplitKeypaths(pInfo->allocator, pInfo->keyPaths, &keys, &newKeyPaths);
+
+ if (keys) {
+ CFStringRef countString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("%ld"), count);
+ if (!CFSetContainsValue(keys, countString)) pInfo->skip = true;
+ __CFPListRelease(countString, pInfo->allocator);
+ count++;
+ pInfo->keyPaths = newKeyPaths;
}
+ result = getContentObject(pInfo, NULL, &tmp);
+ if (keys) {
+ pInfo->keyPaths = oldKeyPaths;
+ pInfo->skip = false;
+ }
+
+ while (result) {
+ if (tmp) {
+ CFArrayAppendValue(array, tmp);
+ __CFPListRelease(tmp, pInfo->allocator);
+ }
+
+ if (keys) {
+ // prep for getting next object
+ CFStringRef countString = CFStringCreateWithFormat(pInfo->allocator, NULL, CFSTR("%ld"), count);
+ if (!CFSetContainsValue(keys, countString)) pInfo->skip = true;
+ __CFPListRelease(countString, pInfo->allocator);
+ count++;
+ pInfo->keyPaths = newKeyPaths;
+ }
+ result = getContentObject(pInfo, NULL, &tmp);
+ if (keys) {
+ // reset after getting object
+ pInfo->keyPaths = oldKeyPaths;
+ pInfo->skip = false;
+ }
+
+ }
+
+ __CFPListRelease(newKeyPaths, pInfo->allocator);
+ __CFPListRelease(keys, pInfo->allocator);
+
if (pInfo->error) { // getContentObject encountered a parse error
- __CFPListRelease(array, pInfo);
- return NULL;
+ __CFPListRelease(array, pInfo->allocator);
+ return false;
}
- if (checkForCloseTag(pInfo, CFXMLPlistTags[ARRAY_IX], ARRAY_TAG_LENGTH)) {
- if (-1 == allowImmutableCollections) checkImmutableCollections();
- if (1 == allowImmutableCollections) {
- if (pInfo->mutabilityOption == kCFPropertyListImmutable) {
- CFArrayRef newArray = CFArrayCreateCopy(pInfo->allocator, array);
- __CFPListRelease(array, pInfo);
- array = (CFMutableArrayRef)newArray;
- }
- }
- return array;
+ if (!checkForCloseTag(pInfo, CFXMLPlistTags[ARRAY_IX], ARRAY_TAG_LENGTH)) {
+ __CFPListRelease(array, pInfo->allocator);
+ return false;
}
- __CFPListRelease(array, pInfo);
- return NULL;
+ if (-1 == allowImmutableCollections) {
+ checkImmutableCollections();
+ }
+ if (1 == allowImmutableCollections) {
+ if (pInfo->mutabilityOption == kCFPropertyListImmutable) {
+ CFArrayRef newArray = CFArrayCreateCopy(pInfo->allocator, array);
+ __CFPListRelease(array, pInfo->allocator);
+ array = (CFMutableArrayRef)newArray;
+ }
+ }
+ *out = array;
+ return true;
}
-static CFTypeRef parseDictTag(_CFXMLPlistParseInfo *pInfo) {
- CFMutableDictionaryRef dict = NULL;
- CFTypeRef key=NULL, value=NULL;
+static Boolean parseDictTag(_CFXMLPlistParseInfo *pInfo, CFTypeRef *out) {
Boolean gotKey;
- const UniChar *base = pInfo->curr;
- key = getContentObject(pInfo, &gotKey);
- while (key) {
- if (!gotKey) {
- __CFPListRelease(key, pInfo);
- __CFPListRelease(dict, pInfo);
- pInfo->curr = base;
- if (!pInfo->error) {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Found non-key inside <dict> at line %d"), lineNumber(pInfo));
+ Boolean result;
+ CFTypeRef key = NULL, value = NULL;
+
+ if (pInfo->skip) {
+ result = getContentObject(pInfo, &gotKey, &key);
+ while (result) {
+ if (!gotKey) {
+ if (!pInfo->error) pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Found non-key inside <dict> at line %d"), lineNumber(pInfo));
+ return false;
}
- return NULL;
- }
- value = getContentObject(pInfo, NULL);
- if (!value) {
- __CFPListRelease(key, pInfo);
- __CFPListRelease(dict, pInfo);
- if (!pInfo->error) {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Value missing for key inside <dict> at line %d"), lineNumber(pInfo));
+ result = getContentObject(pInfo, NULL, &value);
+ if (!result) {
+ if (!pInfo->error) pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Value missing for key inside <dict> at line %d"), lineNumber(pInfo));
+ return false;
}
- return NULL;
+ // key and value should be null, but we'll release just in case here
+ __CFPListRelease(key, pInfo->allocator);
+ key = NULL;
+ __CFPListRelease(value, pInfo->allocator);
+ value = NULL;
+ result = getContentObject(pInfo, &gotKey, &key);
+ }
+ if (checkForCloseTag(pInfo, CFXMLPlistTags[DICT_IX], DICT_TAG_LENGTH)) {
+ *out = NULL;
+ return true;
+ } else {
+ return false;
}
- if (NULL == dict) {
- dict = CFDictionaryCreateMutable(pInfo->allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- _CFDictionarySetCapacity(dict, 10);
- }
- CFDictionarySetValue(dict, key, value);
- __CFPListRelease(key, pInfo);
+ }
+
+ CFSetRef oldKeyPaths = pInfo->keyPaths;
+ CFSetRef nextKeyPaths, theseKeyPaths;
+ __CFPropertyListCreateSplitKeypaths(pInfo->allocator, pInfo->keyPaths, &theseKeyPaths, &nextKeyPaths);
+
+ CFMutableDictionaryRef dict = NULL;
+
+ result = getContentObject(pInfo, &gotKey, &key);
+ while (result && key) {
+ if (!gotKey) {
+ if (!pInfo->error) pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Found non-key inside <dict> at line %d"), lineNumber(pInfo));
+ __CFPListRelease(key, pInfo->allocator);
+ __CFPListRelease(nextKeyPaths, pInfo->allocator);
+ __CFPListRelease(theseKeyPaths, pInfo->allocator);
+ __CFPListRelease(dict, pInfo->allocator);
+ return false;
+ }
+
+ if (theseKeyPaths) {
+ if (!CFSetContainsValue(theseKeyPaths, key)) pInfo->skip = true;
+ pInfo->keyPaths = nextKeyPaths;
+ }
+ result = getContentObject(pInfo, NULL, &value);
+ if (theseKeyPaths) {
+ pInfo->keyPaths = oldKeyPaths;
+ pInfo->skip = false;
+ }
+
+ if (!result) {
+ if (!pInfo->error) pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Value missing for key inside <dict> at line %d"), lineNumber(pInfo));
+ __CFPListRelease(key, pInfo->allocator);
+ __CFPListRelease(nextKeyPaths, pInfo->allocator);
+ __CFPListRelease(theseKeyPaths, pInfo->allocator);
+ __CFPListRelease(dict, pInfo->allocator);
+ return false;
+ }
+
+ if (key && value) {
+ if (NULL == dict) {
+ dict = CFDictionaryCreateMutable(pInfo->allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ _CFDictionarySetCapacity(dict, 10);
+ }
+ CFDictionarySetValue(dict, key, value);
+ }
+
+ __CFPListRelease(key, pInfo->allocator);
key = NULL;
- __CFPListRelease(value, pInfo);
+ __CFPListRelease(value, pInfo->allocator);
value = NULL;
- base = pInfo->curr;
- key = getContentObject(pInfo, &gotKey);
+
+ result = getContentObject(pInfo, &gotKey, &key);
}
+
+ __CFPListRelease(nextKeyPaths, pInfo->allocator);
+ __CFPListRelease(theseKeyPaths, pInfo->allocator);
+
if (checkForCloseTag(pInfo, CFXMLPlistTags[DICT_IX], DICT_TAG_LENGTH)) {
if (NULL == dict) {
if (pInfo->mutabilityOption == kCFPropertyListImmutable) {
uint32_t v;
CFNumberGetValue((CFNumberRef)val, kCFNumberSInt32Type, &v);
uid = (CFTypeRef)_CFKeyedArchiverUIDCreate(pInfo->allocator, v);
- __CFPListRelease(dict, pInfo);
- return uid;
+ __CFPListRelease(dict, pInfo->allocator);
+ *out = uid;
+ return true;
}
}
if (-1 == allowImmutableCollections) checkImmutableCollections();
if (1 == allowImmutableCollections) {
if (pInfo->mutabilityOption == kCFPropertyListImmutable) {
CFDictionaryRef newDict = CFDictionaryCreateCopy(pInfo->allocator, dict);
- __CFPListRelease(dict, pInfo);
+ __CFPListRelease(dict, pInfo->allocator);
dict = (CFMutableDictionaryRef)newDict;
}
}
}
- return dict;
+ *out = dict;
+ return true;
}
- __CFPListRelease(dict, pInfo);
- return NULL;
+
+ return false;
}
-static CFTypeRef parseDataTag(_CFXMLPlistParseInfo *pInfo) {
- CFDataRef result;
- const UniChar *base = pInfo->curr;
- result = __CFPLDataDecode(pInfo, pInfo->mutabilityOption == kCFPropertyListMutableContainersAndLeaves);
- if (!result) {
- pInfo->curr = base;
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Could not interpret <data> at line %d (should be base64-encoded)"), lineNumber(pInfo));
- return NULL;
+static Boolean parseDataTag(_CFXMLPlistParseInfo *pInfo, CFTypeRef *out) {
+ const char *base = pInfo->curr;
+ static const signed char dataDecodeTable[128] = {
+ /* 000 */ -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 010 */ -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 020 */ -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 030 */ -1, -1, -1, -1, -1, -1, -1, -1,
+ /* ' ' */ -1, -1, -1, -1, -1, -1, -1, -1,
+ /* '(' */ -1, -1, -1, 62, -1, -1, -1, 63,
+ /* '0' */ 52, 53, 54, 55, 56, 57, 58, 59,
+ /* '8' */ 60, 61, -1, -1, -1, 0, -1, -1,
+ /* '@' */ -1, 0, 1, 2, 3, 4, 5, 6,
+ /* 'H' */ 7, 8, 9, 10, 11, 12, 13, 14,
+ /* 'P' */ 15, 16, 17, 18, 19, 20, 21, 22,
+ /* 'X' */ 23, 24, 25, -1, -1, -1, -1, -1,
+ /* '`' */ -1, 26, 27, 28, 29, 30, 31, 32,
+ /* 'h' */ 33, 34, 35, 36, 37, 38, 39, 40,
+ /* 'p' */ 41, 42, 43, 44, 45, 46, 47, 48,
+ /* 'x' */ 49, 50, 51, -1, -1, -1, -1, -1
+ };
+
+ int tmpbufpos = 0;
+ int tmpbuflen = 256;
+ uint8_t *tmpbuf = pInfo->skip ? NULL : (uint8_t *)CFAllocatorAllocate(pInfo->allocator, tmpbuflen, 0);
+ int numeq = 0;
+ int acc = 0;
+ int cntr = 0;
+
+ for (; pInfo->curr < pInfo->end; pInfo->curr++) {
+ signed char c = *(pInfo->curr);
+ if (c == '<') {
+ break;
+ }
+ if ('=' == c) {
+ numeq++;
+ } else if (!isspace(c)) {
+ numeq = 0;
+ }
+ if (dataDecodeTable[c] < 0)
+ continue;
+ cntr++;
+ acc <<= 6;
+ acc += dataDecodeTable[c];
+ if (!pInfo->skip && 0 == (cntr & 0x3)) {
+ if (tmpbuflen <= tmpbufpos + 2) {
+ if (tmpbuflen < 256 * 1024) {
+ tmpbuflen *= 4;
+ } else if (tmpbuflen < 16 * 1024 * 1024) {
+ tmpbuflen *= 2;
+ } else {
+ // once in this stage, this will be really slow
+ // and really potentially fragment memory
+ tmpbuflen += 256 * 1024;
+ }
+ tmpbuf = (uint8_t *)CFAllocatorReallocate(pInfo->allocator, tmpbuf, tmpbuflen, 0);
+ if (!tmpbuf) HALT; // out of memory
+ }
+ tmpbuf[tmpbufpos++] = (acc >> 16) & 0xff;
+ if (numeq < 2) tmpbuf[tmpbufpos++] = (acc >> 8) & 0xff;
+ if (numeq < 1) tmpbuf[tmpbufpos++] = acc & 0xff;
+ }
+ }
+
+ CFDataRef result = NULL;
+ if (!pInfo->skip) {
+ if (pInfo->mutabilityOption == kCFPropertyListMutableContainersAndLeaves) {
+ result = (CFDataRef)CFDataCreateMutable(pInfo->allocator, 0);
+ CFDataAppendBytes((CFMutableDataRef)result, tmpbuf, tmpbufpos);
+ CFAllocatorDeallocate(pInfo->allocator, tmpbuf);
+ } else {
+ result = CFDataCreateWithBytesNoCopy(pInfo->allocator, tmpbuf, tmpbufpos, pInfo->allocator);
+ }
+ if (!result) {
+ pInfo->curr = base;
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Could not interpret <data> at line %d (should be base64-encoded)"), lineNumber(pInfo));
+ return false;
+ }
+ }
+
+ if (checkForCloseTag(pInfo, CFXMLPlistTags[DATA_IX], DATA_TAG_LENGTH)) {
+ *out = result;
+ return true;
+ } else {
+ __CFPListRelease(result, pInfo->allocator);
+ return false;
}
- if (checkForCloseTag(pInfo, CFXMLPlistTags[DATA_IX], DATA_TAG_LENGTH)) return result;
- __CFPListRelease(result, pInfo);
- return NULL;
}
CF_INLINE Boolean read2DigitNumber(_CFXMLPlistParseInfo *pInfo, int32_t *result) {
- UniChar ch1, ch2;
+ char ch1, ch2;
if (pInfo->curr + 2 >= pInfo->end) return false;
ch1 = *pInfo->curr;
ch2 = *(pInfo->curr + 1);
}
// YYYY '-' MM '-' DD 'T' hh ':' mm ':' ss 'Z'
-static CFTypeRef parseDateTag(_CFXMLPlistParseInfo *pInfo) {
+static Boolean parseDateTag(_CFXMLPlistParseInfo *pInfo, CFTypeRef *out) {
int32_t year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
int32_t num = 0;
Boolean badForm = false;
badForm = true;
}
- if (badForm) {
+ if (badForm || !checkForCloseTag(pInfo, CFXMLPlistTags[DATE_IX], DATE_TAG_LENGTH)) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Could not interpret <date> at line %d"), lineNumber(pInfo));
- return NULL;
+ return false;
}
- if (!checkForCloseTag(pInfo, CFXMLPlistTags[DATE_IX], DATE_TAG_LENGTH)) return NULL;
CFAbsoluteTime at = 0.0;
#if 1
CFGregorianDate date = {yearIsNegative ? -year : year, month, day, hour, minute, second};
at = CFGregorianDateGetAbsoluteTime(date, NULL);
#else
+ // this doesn't work
CFCalendarRef calendar = CFCalendarCreateWithIdentifier(kCFAllocatorSystemDefault, kCFCalendarIdentifierGregorian);
CFTimeZoneRef tz = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, CFSTR("GMT"), true);
CFCalendarSetTimeZone(calendar, tz);
CFRelease(calendar);
CFRelease(tz);
#endif
- return CFDateCreate(pInfo->allocator, at);
+ if (pInfo->skip) {
+ *out = NULL;
+ } else {
+ *out = CFDateCreate(pInfo->allocator, at);
+ }
+ return true;
}
-static CFTypeRef parseRealTag(_CFXMLPlistParseInfo *pInfo) {
- CFStringRef str = getString(pInfo);
- SInt32 idx, len;
- double val;
- CFNumberRef result;
- CFStringInlineBuffer buf;
- if (!str) {
- if (!pInfo->error) {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered empty <real> on line %d"), lineNumber(pInfo));
- }
- return NULL;
+static Boolean parseRealTag(_CFXMLPlistParseInfo *pInfo, CFTypeRef *out) {
+ CFStringRef str = NULL;
+ if (!parseStringTag(pInfo, &str)) {
+ if (!pInfo->error) pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered empty <real> on line %d"), lineNumber(pInfo));
+ return false;
}
- if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("nan"), kCFCompareCaseInsensitive)) {
- __CFPListRelease(str, pInfo);
- return (checkForCloseTag(pInfo, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH)) ? CFRetain(kCFNumberNaN) : NULL;
- }
- if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("+infinity"), kCFCompareCaseInsensitive)) {
- __CFPListRelease(str, pInfo);
- return (checkForCloseTag(pInfo, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH)) ? CFRetain(kCFNumberPositiveInfinity) : NULL;
- }
- if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("-infinity"), kCFCompareCaseInsensitive)) {
- __CFPListRelease(str, pInfo);
- return (checkForCloseTag(pInfo, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH)) ? CFRetain(kCFNumberNegativeInfinity) : NULL;
- }
- if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("infinity"), kCFCompareCaseInsensitive)) {
- __CFPListRelease(str, pInfo);
- return (checkForCloseTag(pInfo, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH)) ? CFRetain(kCFNumberPositiveInfinity) : NULL;
- }
- if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("-inf"), kCFCompareCaseInsensitive)) {
- __CFPListRelease(str, pInfo);
- return (checkForCloseTag(pInfo, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH)) ? CFRetain(kCFNumberNegativeInfinity) : NULL;
- }
- if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("inf"), kCFCompareCaseInsensitive)) {
- __CFPListRelease(str, pInfo);
- return (checkForCloseTag(pInfo, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH)) ? CFRetain(kCFNumberPositiveInfinity) : NULL;
- }
- if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("+inf"), kCFCompareCaseInsensitive)) {
- __CFPListRelease(str, pInfo);
- return (checkForCloseTag(pInfo, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH)) ? CFRetain(kCFNumberPositiveInfinity) : NULL;
- }
-
- len = CFStringGetLength(str);
- CFStringInitInlineBuffer(str, &buf, CFRangeMake(0, len));
- idx = 0;
- if (!__CFStringScanDouble(&buf, NULL, &idx, &val) || idx != len) {
- __CFPListRelease(str, pInfo);
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered misformatted real on line %d"), lineNumber(pInfo));
- return NULL;
+ CFNumberRef result = NULL;
+
+ if (!pInfo->skip) {
+ if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("nan"), kCFCompareCaseInsensitive)) result = kCFNumberNaN;
+ else if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("+infinity"), kCFCompareCaseInsensitive)) result = kCFNumberPositiveInfinity;
+ else if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("-infinity"), kCFCompareCaseInsensitive)) result = kCFNumberNegativeInfinity;
+ else if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("infinity"), kCFCompareCaseInsensitive)) result = kCFNumberPositiveInfinity;
+ else if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("-inf"), kCFCompareCaseInsensitive)) result = kCFNumberNegativeInfinity;
+ else if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("inf"), kCFCompareCaseInsensitive)) result = kCFNumberPositiveInfinity;
+ else if (kCFCompareEqualTo == CFStringCompare(str, CFSTR("+inf"), kCFCompareCaseInsensitive)) result = kCFNumberPositiveInfinity;
+
+ if (result) {
+ CFRetain(result);
+ } else {
+ CFIndex len = CFStringGetLength(str);
+ CFStringInlineBuffer buf;
+ CFStringInitInlineBuffer(str, &buf, CFRangeMake(0, len));
+ SInt32 idx = 0;
+ double val;
+ if (!__CFStringScanDouble(&buf, NULL, &idx, &val) || idx != len) {
+ __CFPListRelease(str, pInfo->allocator);
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered misformatted real on line %d"), lineNumber(pInfo));
+ return false;
+ }
+ result = CFNumberCreate(pInfo->allocator, kCFNumberDoubleType, &val);
+ }
+ }
+
+ __CFPListRelease(str, pInfo->allocator);
+ if (checkForCloseTag(pInfo, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH)) {
+ *out = result;
+ return true;
+ } else {
+ __CFPListRelease(result, pInfo->allocator);
+ return false;
}
- __CFPListRelease(str, pInfo);
- result = CFNumberCreate(pInfo->allocator, kCFNumberDoubleType, &val);
- if (checkForCloseTag(pInfo, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH)) return result;
- __CFPListRelease(result, pInfo);
- return NULL;
}
#define GET_CH if (pInfo->curr == pInfo->end) { \
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Premature end of file after <integer> on line %d"), lineNumber(pInfo)); \
- return NULL; \
+ return false; \
} \
ch = *(pInfo->curr)
kCFNumberSInt128Type = 17
};
-static CFTypeRef parseIntegerTag(_CFXMLPlistParseInfo *pInfo) {
+CF_INLINE bool isWhitespace(const char *utf8bytes, const char *end) {
+ // Converted UTF-16 isWhitespace from CFString to UTF8 bytes to get full list of UTF8 whitespace
+ /*
+ 0020 -> <20>
+ 0009 -> <09>
+ 00a0 -> <c2a0>
+ 1680 -> <e19a80>
+ 2000 -> <e28080>
+ 2001 -> <e28081>
+ 2002 -> <e28082>
+ 2003 -> <e28083>
+ 2004 -> <e28084>
+ 2005 -> <e28085>
+ 2006 -> <e28086>
+ 2007 -> <e28087>
+ 2008 -> <e28088>
+ 2009 -> <e28089>
+ 200a -> <e2808a>
+ 200b -> <e2808b>
+ 202f -> <e280af>
+ 205f -> <e2819f>
+ 3000 -> <e38080>
+ */
+ // Except we consider some additional values from 0x0 to 0x21 and 0x7E to 0xA1 as whitespace, for compatability
+ 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);
+ if (byte1 == 0xe2 && byte2 == 0x80) {
+ return ((byte3 >= 80 && byte3 <= 0x8b) || byte3 == 0xaf);
+ } else if (byte1 == 0xe2 && byte2 == 0x81) {
+ return byte3 == 0x9f;
+ } else if (byte1 == 0xe3 && byte2 == 0x80 && byte3 == 0x80) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static Boolean parseIntegerTag(_CFXMLPlistParseInfo *pInfo, CFTypeRef *out) {
bool isHex = false, isNeg = false, hadLeadingZero = false;
- UniChar ch = 0;
+ char ch = 0;
// decimal_constant S*(-|+)?S*[0-9]+ (S == space)
// hex_constant S*(-|+)?S*0[xX][0-9a-fA-F]+ (S == space)
- while (pInfo->curr < pInfo->end && __CFIsWhitespace(*(pInfo->curr))) pInfo->curr++;
+ while (pInfo->curr < pInfo->end && isWhitespace(pInfo->curr, pInfo->end)) pInfo->curr++;
GET_CH;
if ('<' == ch) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered empty <integer> on line %d"), lineNumber(pInfo));
- return NULL;
+ return false;
}
if ('-' == ch || '+' == ch) {
isNeg = ('-' == ch);
pInfo->curr++;
- while (pInfo->curr < pInfo->end && __CFIsWhitespace(*(pInfo->curr))) pInfo->curr++;
+ while (pInfo->curr < pInfo->end && isWhitespace(pInfo->curr, pInfo->end)) pInfo->curr++;
}
GET_CH;
if ('0' == ch) {
int32_t val = 0;
if (!checkForCloseTag(pInfo, CFXMLPlistTags[INTEGER_IX], INTEGER_TAG_LENGTH)) {
// checkForCloseTag() sets error string
- return NULL;
+ return false;
}
- return CFNumberCreate(pInfo->allocator, kCFNumberSInt32Type, &val);
+ if (pInfo->skip) {
+ *out = NULL;
+ } else {
+ *out = CFNumberCreate(pInfo->allocator, kCFNumberSInt32Type, &val);
+ }
+ return true;
}
if ('<' == ch) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Incomplete <integer> on line %d"), lineNumber(pInfo));
- return NULL;
+ return false;
}
uint64_t value = 0;
uint32_t multiplier = (isHex ? 16 : 10);
break;
default: // other character
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unknown character '%c' (0x%x) in <integer> on line %d"), ch, ch, lineNumber(pInfo));
- return NULL;
+ return false;
}
if (!isHex && new_digit > 9) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Hex digit in non-hex <integer> on line %d"), lineNumber(pInfo));
- return NULL;
+ return false;
}
if (UINT64_MAX / multiplier < value) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Integer overflow in <integer> on line %d"), lineNumber(pInfo));
- return NULL;
+ return false;
}
value = multiplier * value;
if (UINT64_MAX - new_digit < value) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Integer overflow in <integer> on line %d"), lineNumber(pInfo));
- return NULL;
+ return false;
}
value = value + new_digit;
if (isNeg && (uint64_t)INT64_MAX + 1 < value) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Integer underflow in <integer> on line %d"), lineNumber(pInfo));
- return NULL;
+ return false;
}
pInfo->curr++;
GET_CH;
}
if (!checkForCloseTag(pInfo, CFXMLPlistTags[INTEGER_IX], INTEGER_TAG_LENGTH)) {
// checkForCloseTag() sets error string
- return NULL;
+ return false;
}
- if (isNeg || value <= INT64_MAX) {
- int64_t v = value;
- if (isNeg) v = -v; // no-op if INT64_MIN
- return CFNumberCreate(pInfo->allocator, kCFNumberSInt64Type, &v);
+
+ if (pInfo->skip) {
+ *out = NULL;
+ } else {
+ if (isNeg || value <= INT64_MAX) {
+ int64_t v = value;
+ if (isNeg) v = -v; // no-op if INT64_MIN
+ *out = CFNumberCreate(pInfo->allocator, kCFNumberSInt64Type, &v);
+ } else {
+ CFSInt128Struct val;
+ val.high = 0;
+ val.low = value;
+ *out = CFNumberCreate(pInfo->allocator, kCFNumberSInt128Type, &val);
+ }
}
- CFSInt128Struct val;
- val.high = 0;
- val.low = value;
- return CFNumberCreate(pInfo->allocator, kCFNumberSInt128Type, &val);
+ return true;
}
#undef GET_CH
// Returned object is retained; caller must free. pInfo->curr expected to point to the first character after the '<'
-static CFTypeRef parseXMLElement(_CFXMLPlistParseInfo *pInfo, Boolean *isKey) {
- const UniChar *marker = pInfo->curr;
+static Boolean parseXMLElement(_CFXMLPlistParseInfo *pInfo, Boolean *isKey, CFTypeRef *out) {
+ const char *marker = pInfo->curr;
int markerLength = -1;
Boolean isEmpty;
int markerIx = -1;
if (isKey) *isKey = false;
while (pInfo->curr < pInfo->end) {
- UniChar ch = *(pInfo->curr);
+ char ch = *(pInfo->curr);
if (ch == ' ' || ch == '\t' || ch == '\n' || ch =='\r') {
if (markerLength == -1) markerLength = pInfo->curr - marker;
} else if (ch == '>') {
}
pInfo->curr ++;
}
- if (pInfo->curr >= pInfo->end) return NULL;
+ if (pInfo->curr >= pInfo->end) return false;
isEmpty = (*(pInfo->curr-1) == '/');
if (markerLength == -1)
markerLength = pInfo->curr - (isEmpty ? 1 : 0) - marker;
// Back up to the beginning of the marker
pInfo->curr = marker;
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Malformed tag on line %d"), lineNumber(pInfo));
- return NULL;
+ return false;
}
switch (*marker) {
case 'a': // Array
- if (markerLength == ARRAY_TAG_LENGTH && matchString(marker, CFXMLPlistTags[ARRAY_IX], ARRAY_TAG_LENGTH))
+ if (markerLength == ARRAY_TAG_LENGTH && !memcmp(marker, CFXMLPlistTags[ARRAY_IX], ARRAY_TAG_LENGTH))
markerIx = ARRAY_IX;
break;
case 'd': // Dictionary, data, or date; Fortunately, they all have the same marker length....
if (markerLength != DICT_TAG_LENGTH)
break;
- if (matchString(marker, CFXMLPlistTags[DICT_IX], DICT_TAG_LENGTH))
+ if (!memcmp(marker, CFXMLPlistTags[DICT_IX], DICT_TAG_LENGTH))
markerIx = DICT_IX;
- else if (matchString(marker, CFXMLPlistTags[DATA_IX], DATA_TAG_LENGTH))
+ else if (!memcmp(marker, CFXMLPlistTags[DATA_IX], DATA_TAG_LENGTH))
markerIx = DATA_IX;
- else if (matchString(marker, CFXMLPlistTags[DATE_IX], DATE_TAG_LENGTH))
+ else if (!memcmp(marker, CFXMLPlistTags[DATE_IX], DATE_TAG_LENGTH))
markerIx = DATE_IX;
break;
case 'f': // false (boolean)
- if (markerLength == FALSE_TAG_LENGTH && matchString(marker, CFXMLPlistTags[FALSE_IX], FALSE_TAG_LENGTH)) {
+ if (markerLength == FALSE_TAG_LENGTH && !memcmp(marker, CFXMLPlistTags[FALSE_IX], FALSE_TAG_LENGTH)) {
markerIx = FALSE_IX;
}
break;
case 'i': // integer
- if (markerLength == INTEGER_TAG_LENGTH && matchString(marker, CFXMLPlistTags[INTEGER_IX], INTEGER_TAG_LENGTH))
+ if (markerLength == INTEGER_TAG_LENGTH && !memcmp(marker, CFXMLPlistTags[INTEGER_IX], INTEGER_TAG_LENGTH))
markerIx = INTEGER_IX;
break;
case 'k': // Key of a dictionary
- if (markerLength == KEY_TAG_LENGTH && matchString(marker, CFXMLPlistTags[KEY_IX], KEY_TAG_LENGTH)) {
+ if (markerLength == KEY_TAG_LENGTH && !memcmp(marker, CFXMLPlistTags[KEY_IX], KEY_TAG_LENGTH)) {
markerIx = KEY_IX;
if (isKey) *isKey = true;
}
break;
case 'p': // Plist
- if (markerLength == PLIST_TAG_LENGTH && matchString(marker, CFXMLPlistTags[PLIST_IX], PLIST_TAG_LENGTH))
+ if (markerLength == PLIST_TAG_LENGTH && !memcmp(marker, CFXMLPlistTags[PLIST_IX], PLIST_TAG_LENGTH))
markerIx = PLIST_IX;
break;
case 'r': // real
- if (markerLength == REAL_TAG_LENGTH && matchString(marker, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH))
+ if (markerLength == REAL_TAG_LENGTH && !memcmp(marker, CFXMLPlistTags[REAL_IX], REAL_TAG_LENGTH))
markerIx = REAL_IX;
break;
case 's': // String
- if (markerLength == STRING_TAG_LENGTH && matchString(marker, CFXMLPlistTags[STRING_IX], STRING_TAG_LENGTH))
+ if (markerLength == STRING_TAG_LENGTH && !memcmp(marker, CFXMLPlistTags[STRING_IX], STRING_TAG_LENGTH))
markerIx = STRING_IX;
break;
case 't': // true (boolean)
- if (markerLength == TRUE_TAG_LENGTH && matchString(marker, CFXMLPlistTags[TRUE_IX], TRUE_TAG_LENGTH))
+ if (markerLength == TRUE_TAG_LENGTH && !memcmp(marker, CFXMLPlistTags[TRUE_IX], TRUE_TAG_LENGTH))
markerIx = TRUE_IX;
break;
}
if (!pInfo->allowNewTypes && markerIx != PLIST_IX && markerIx != ARRAY_IX && markerIx != DICT_IX && markerIx != STRING_IX && markerIx != KEY_IX && markerIx != DATA_IX) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered new tag when expecting only old-style property list objects"));
- return NULL;
+ return false;
}
switch (markerIx) {
case PLIST_IX:
if (isEmpty) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered empty plist tag"));
- return NULL;
+ return false;
}
- return parsePListTag(pInfo);
+ return parsePListTag(pInfo, out);
case ARRAY_IX:
if (isEmpty) {
- return pInfo->mutabilityOption == kCFPropertyListImmutable ? CFArrayCreate(pInfo->allocator, NULL, 0, &kCFTypeArrayCallBacks) : CFArrayCreateMutable(pInfo->allocator, 0, &kCFTypeArrayCallBacks);
+ if (pInfo->skip) {
+ *out = NULL;
+ } else {
+ if (pInfo->mutabilityOption == kCFPropertyListImmutable) {
+ *out = CFArrayCreate(pInfo->allocator, NULL, 0, &kCFTypeArrayCallBacks);
+ } else {
+ *out = CFArrayCreateMutable(pInfo->allocator, 0, &kCFTypeArrayCallBacks);
+ }
+ }
+ return true;
} else {
- return parseArrayTag(pInfo);
+ return parseArrayTag(pInfo, out);
}
case DICT_IX:
if (isEmpty) {
- if (pInfo->mutabilityOption == kCFPropertyListImmutable) {
- return CFDictionaryCreate(pInfo->allocator, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (pInfo->skip) {
+ *out = NULL;
} else {
- return CFDictionaryCreateMutable(pInfo->allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (pInfo->mutabilityOption == kCFPropertyListImmutable) {
+ *out = CFDictionaryCreate(pInfo->allocator, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ } else {
+ *out = CFDictionaryCreateMutable(pInfo->allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ }
}
+ return true;
} else {
- return parseDictTag(pInfo);
+ return parseDictTag(pInfo, out);
}
case KEY_IX:
case STRING_IX:
{
- CFStringRef str;
int tagLen = (markerIx == KEY_IX) ? KEY_TAG_LENGTH : STRING_TAG_LENGTH;
if (isEmpty) {
- return pInfo->mutabilityOption == kCFPropertyListMutableContainersAndLeaves ? CFStringCreateMutable(pInfo->allocator, 0) : CFStringCreateWithCharacters(pInfo->allocator, NULL, 0);
+ if (pInfo->skip) {
+ *out = NULL;
+ } else {
+ if (pInfo->mutabilityOption == kCFPropertyListMutableContainersAndLeaves) {
+ *out = CFStringCreateMutable(pInfo->allocator, 0);
+ } else {
+ *out = CFStringCreateWithCharacters(pInfo->allocator, NULL, 0);
+ }
+ }
+ return true;
+ }
+ if (!parseStringTag(pInfo, (CFStringRef *)out)) {
+ return false; // parseStringTag will already have set the error string
}
- str = getString(pInfo);
- if (!str) return NULL; // getString will already have set the error string
if (!checkForCloseTag(pInfo, CFXMLPlistTags[markerIx], tagLen)) {
- __CFPListRelease(str, pInfo);
- return NULL;
+ __CFPListRelease(*out, pInfo->allocator);
+ return false;
+ } else {
+ return true;
}
- return str;
}
case DATA_IX:
if (isEmpty) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered empty <data> on line %d"), lineNumber(pInfo));
- return NULL;
+ return false;
} else {
- return parseDataTag(pInfo);
+ return parseDataTag(pInfo, out);
}
case DATE_IX:
if (isEmpty) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered empty <date> on line %d"), lineNumber(pInfo));
- return NULL;
+ return false;
} else {
- return parseDateTag(pInfo);
+ return parseDateTag(pInfo, out);
}
case TRUE_IX:
if (!isEmpty) {
- if (!checkForCloseTag(pInfo, CFXMLPlistTags[TRUE_IX], TRUE_TAG_LENGTH)) return NULL;
+ if (!checkForCloseTag(pInfo, CFXMLPlistTags[TRUE_IX], TRUE_TAG_LENGTH)) {
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered non-empty <true> on line %d"), lineNumber(pInfo));
+ return false;
+ }
}
- return CFRetain(kCFBooleanTrue);
+ if (pInfo->skip) {
+ *out = NULL;
+ } else {
+ *out = CFRetain(kCFBooleanTrue);
+ }
+ return true;
case FALSE_IX:
if (!isEmpty) {
- if (!checkForCloseTag(pInfo, CFXMLPlistTags[FALSE_IX], FALSE_TAG_LENGTH)) return NULL;
+ if (!checkForCloseTag(pInfo, CFXMLPlistTags[FALSE_IX], FALSE_TAG_LENGTH)) {
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered non-empty <false> on line %d"), lineNumber(pInfo));
+ return false;
+ }
}
- return CFRetain(kCFBooleanFalse);
+ if (pInfo->skip) {
+ *out = NULL;
+ } else {
+ *out = CFRetain(kCFBooleanFalse);
+ }
+ return true;
case REAL_IX:
if (isEmpty) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered empty <real> on line %d"), lineNumber(pInfo));
- return NULL;
+ return false;
} else {
- return parseRealTag(pInfo);
+ return parseRealTag(pInfo, out);
}
case INTEGER_IX:
if (isEmpty) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered empty <integer> on line %d"), lineNumber(pInfo));
- return NULL;
+ return false;
} else {
- return parseIntegerTag(pInfo);
+ return parseIntegerTag(pInfo, out);
}
default: {
- CFStringRef markerStr = CFStringCreateWithCharacters(pInfo->allocator, marker, markerLength);
+ CFStringRef markerStr = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (const UInt8 *)marker, markerLength, kCFStringEncodingUTF8, NO);
pInfo->curr = marker;
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unknown tag %@ on line %d"), markerStr, lineNumber(pInfo));
- __CFPListRelease(markerStr, pInfo);
- return NULL;
+ pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unknown tag %@ on line %d"), markerStr ? markerStr : CFSTR("<unknown>"), lineNumber(pInfo));
+ if (markerStr) CFRelease(markerStr);
+ return false;
}
}
}
-static CFTypeRef parseXMLPropertyList(_CFXMLPlistParseInfo *pInfo) {
+static Boolean parseXMLPropertyList(_CFXMLPlistParseInfo *pInfo, CFTypeRef *out) {
while (!pInfo->error && pInfo->curr < pInfo->end) {
UniChar ch;
skipWhitespace(pInfo);
if (pInfo->curr+1 >= pInfo->end) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("No XML content found"));
- return NULL;
+ return false;
}
if (*(pInfo->curr) != '<') {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unexpected character %c at line %d"), *(pInfo->curr), lineNumber(pInfo));
- return NULL;
+ return false;
}
ch = *(++ pInfo->curr);
if (ch == '!') {
skipXMLProcessingInstruction(pInfo);
} else {
// Tag or malformed
- return parseXMLElement(pInfo, NULL);
+ return parseXMLElement(pInfo, NULL, out);
// Note we do not verify that there was only one element, so a file that has garbage after the first element will nonetheless successfully parse
}
}
if (!(pInfo->error)) {
pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unexpected EOF"));
}
- return NULL;
+ return false;
}
-static CFStringEncoding encodingForXMLData(CFDataRef data, CFErrorRef *error) {
+static CFStringEncoding encodingForXMLData(CFDataRef data, CFErrorRef *error, CFIndex *skip) {
const uint8_t *bytes = (uint8_t *)CFDataGetBytePtr(data);
UInt32 length = CFDataGetLength(data);
const uint8_t *idx, *end;
char quote;
- // Check for the byte order mark first
- if (length > 2 &&
- ((*bytes == 0xFF && *(bytes+1) == 0xFE) ||
- (*bytes == 0xFE && *(bytes+1) == 0xFF) ||
- *bytes == 0x00 || *(bytes+1) == 0x00)) // This clause checks for a Unicode sequence lacking the byte order mark; technically an error, but this check is recommended by the XML spec
- return kCFStringEncodingUnicode;
+ // Check for the byte order mark first. If we find it, set the skip value so the parser doesn't attempt to parse the BOM itself.
+ if (length > 4) {
+ if (*bytes == 0x00 && *(bytes+1) == 0x00 && *(bytes+2) == 0xFE && *(bytes+3) == 0xFF) {
+ *skip = 4;
+ return kCFStringEncodingUTF32BE;
+ } else if (*bytes == 0xFF && *(bytes+1) == 0xFE && *(bytes+2) == 0x00 && *(bytes+3) == 0x00) {
+ *skip = 4;
+ return kCFStringEncodingUTF32LE;
+ }
+ }
+ if (length > 3) {
+ if (*bytes == 0xEF && *(bytes+1) == 0xBB && *(bytes+2) == 0xBF) {
+ *skip = 3;
+ return kCFStringEncodingUTF8;
+ }
+ }
+
+ if (length > 2) {
+ if (*bytes == 0xFF && *(bytes+1) == 0xFE) {
+ *skip = 2;
+ return kCFStringEncodingUTF16LE;
+ } else if (*bytes == 0xFE && *(bytes+1) == 0xFF) {
+ *skip = 2;
+ return kCFStringEncodingUTF16BE;
+ } else if (*bytes == 0x00 || *(bytes+1) == 0x00) { // This clause checks for a Unicode sequence lacking the byte order mark; technically an error, but this check is recommended by the XML spec
+ *skip = 2;
+ return kCFStringEncodingUnicode;
+ }
+ }
+
// Scan for the <?xml.... ?> opening
if (length < 5 || strncmp((char const *) bytes, "<?xml", 5) != 0) return kCFStringEncodingUTF8;
idx = bytes + 5;
else {
CFStringRef encodingName;
const uint8_t *base = idx+1; // Move past the quote character
- CFStringEncoding enc;
UInt32 len;
idx ++;
while (idx < end && *idx != quote) idx ++;
if (len == 5 && (*base == 'u' || *base == 'U') && (base[1] == 't' || base[1] == 'T') && (base[2] == 'f' || base[2] == 'F') && (base[3] == '-') && (base[4] == '8'))
return kCFStringEncodingUTF8;
encodingName = CFStringCreateWithBytes(kCFAllocatorSystemDefault, base, len, kCFStringEncodingISOLatin1, false);
- enc = CFStringConvertIANACharSetNameToEncoding(encodingName);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
+ CFStringEncoding enc = CFStringConvertIANACharSetNameToEncoding(encodingName);
if (enc != kCFStringEncodingInvalidId) {
CFRelease(encodingName);
return enc;
}
+#endif
if (error) {
*error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unknown encoding (%@)"), encodingName);
}
bool __CFTryParseBinaryPlist(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFPropertyListRef *plist, CFStringRef *errorString);
-unsigned long _CFPropertyListAllowNonUTF8 = 0;
#define SAVE_PLISTS 0
}
#endif
-
-CFTypeRef _CFPropertyListCreateFromXMLStringError(CFAllocatorRef allocator, CFStringRef xmlString, CFOptionFlags option, CFErrorRef *error, Boolean allowNewTypes, CFPropertyListFormat *format) {
+// If the data is from a converted string, then originalString is non-NULL. If originalString is NULL, then pass in guessedEncoding.
+// keyPaths is a set of CFStrings, ':'-separated paths
+static Boolean _CFPropertyListCreateFromUTF8Data(CFAllocatorRef allocator, CFDataRef xmlData, CFIndex skipBytes, CFStringRef originalString, CFStringEncoding guessedEncoding, CFOptionFlags option, CFErrorRef *outError, Boolean allowNewTypes, CFPropertyListFormat *format, CFSetRef keyPaths, CFTypeRef *out) {
initStatics();
- CFAssert1(xmlString != NULL, __kCFLogAssertion, "%s(): NULL string not allowed", __PRETTY_FUNCTION__);
+ CFAssert1(xmlData != NULL, __kCFLogAssertion, "%s(): NULL data not allowed", __PRETTY_FUNCTION__);
CFAssert2(option == kCFPropertyListImmutable || option == kCFPropertyListMutableContainers || option == kCFPropertyListMutableContainersAndLeaves, __kCFLogAssertion, "%s(): Unrecognized option %d", __PRETTY_FUNCTION__, option);
- UInt32 length;
- Boolean createdBuffer = false;
- length = xmlString ? CFStringGetLength(xmlString) : 0;
-
+ CFIndex length = CFDataGetLength(xmlData);
if (!length) {
- if (error) {
- *error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Conversion of string failed. The string is empty."));
- }
- return NULL;
+ if (outError) *outError = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Conversion of string failed. The string is empty."));
+ return false;
}
_CFXMLPlistParseInfo pInfoBuf;
_CFXMLPlistParseInfo *pInfo = &pInfoBuf;
CFTypeRef result;
- // Ensure that xmlString is not collected while we are using it
- CFRetain(xmlString);
- UniChar *buf = (UniChar *)CFStringGetCharactersPtr(xmlString);
+ // Ensure that the data is not collected while we are using it
+ CFRetain(xmlData);
+ const char *buf = (const char *)CFDataGetBytePtr(xmlData);
+
+ // We may have to skip over starting stuff like BOM markers.
+ buf += skipBytes;
- if (!buf) {
- buf = (UniChar *)CFAllocatorAllocate(kCFAllocatorSystemDefault, length * sizeof(UniChar), 0);
- if (!buf) {
- out_of_memory_warning();
- return NULL;
- }
- CFStringGetCharacters(xmlString, CFRangeMake(0, length), buf);
- createdBuffer = true;
- }
pInfo->begin = buf;
pInfo->end = buf+length;
pInfo->curr = buf;
pInfo->allocator = allocator;
pInfo->error = NULL;
- pInfo->stringSet = CFSetCreateMutable(allocator, 0, &kCFTypeSetCallBacks);
- _CFSetSetCapacity(pInfo->stringSet, CFStringGetLength(xmlString) / 250); // avoid lots of rehashes, may waste some memory; simple heuristic
+ _createStringMap(pInfo);
pInfo->mutabilityOption = option;
pInfo->allowNewTypes = allowNewTypes;
+ pInfo->skip = false;
+ pInfo->keyPaths = createTopLevelKeypaths(allocator, keyPaths);
- result = parseXMLPropertyList(pInfo);
- if (result && format) *format = kCFPropertyListXMLFormat_v1_0;
- if (!result) {
- CFErrorRef xmlParserErr = pInfo->error;
- // Reset pInfo so we can try again
- pInfo->curr = pInfo->begin;
- pInfo->error = NULL;
+ Boolean success = parseXMLPropertyList(pInfo, &result);
+ if (success && result && format) *format = kCFPropertyListXMLFormat_v1_0;
+
+ _cleanupStringMap(pInfo);
+ if (pInfo->keyPaths && !_CFAllocatorIsGCRefZero(allocator)) CFRelease(pInfo->keyPaths);
+ CFRelease(xmlData);
+
+ if (success) {
+ *out = result; // caller releases
+ return true;
+ }
+
+ // Try again, old-style
+ CFErrorRef oldStyleError = NULL;
+ result = __CFParseOldStylePropertyListOrStringsFile(allocator, xmlData, originalString, guessedEncoding, option, outError ? &oldStyleError : NULL, format);
+ if (result) {
+ // Release old error, return
+ if (pInfo->error) CFRelease(pInfo->error);
+ *out = result;
+ return true;
+ }
+
+ // Failure, both ways. Set up the error to be given back to caller.
+ if (!outError) {
+ if (pInfo->error) CFRelease(pInfo->error);
+ return false;
+ }
+
+ // Caller's responsibility to release outError
+ if (pInfo->error && oldStyleError) {
+ // Add the error from the old-style property list parser to the user info of the original error (pInfo->error), which had better exist
+ CFDictionaryRef oldUserInfo = CFErrorCopyUserInfo(pInfo->error);
+ CFMutableDictionaryRef newUserInfo = CFDictionaryCreateMutableCopy(kCFAllocatorSystemDefault, CFDictionaryGetCount(oldUserInfo) + 1, oldUserInfo);
+ CFDictionaryAddValue(newUserInfo, CFPropertyListOldStyleParserErrorKey, oldStyleError);
- // Try pList
- result = parseOldStylePropertyListOrStringsFile(pInfo);
- if (result && format) {
- *format = kCFPropertyListOpenStepFormat;
- }
+ // Re-create the xml parser error with this new user info dictionary
+ CFErrorRef newError = CFErrorCreate(kCFAllocatorSystemDefault, CFErrorGetDomain(pInfo->error), CFErrorGetCode(pInfo->error), newUserInfo);
- if (!result && xmlParserErr && error) {
- // Add the new error from the old-style property list parser to the user info of the original error
- CFDictionaryRef xmlUserInfo = CFErrorCopyUserInfo(xmlParserErr);
- CFMutableDictionaryRef userInfo = CFDictionaryCreateMutableCopy(kCFAllocatorSystemDefault, CFDictionaryGetCount(xmlUserInfo) + 1, xmlUserInfo);
- CFDictionaryAddValue(userInfo, CFPropertyListOldStyleParserErrorKey, pInfo->error);
-
- // Re-create the xml parser error with this new user info dictionary
- CFErrorRef newError = CFErrorCreate(kCFAllocatorSystemDefault, CFErrorGetDomain(xmlParserErr), CFErrorGetCode(xmlParserErr), userInfo);
-
- CFRelease(xmlUserInfo);
- CFRelease(userInfo);
-
- // It is the responsibility of the caller to release this newly created error
- *error = newError;
- }
+ CFRelease(oldUserInfo);
+ CFRelease(newUserInfo);
+ CFRelease(oldStyleError);
+ CFRelease(pInfo->error);
+ *outError = newError;
- if (xmlParserErr) {
- CFRelease(xmlParserErr);
+ } else if (pInfo->error && !oldStyleError) {
+ // Return original error
+ *outError = pInfo->error;
+ } else if (!pInfo->error && oldStyleError) {
+ // Return only old-style error
+ // Probably shouldn't get here
+ *outError = oldStyleError;
+ } else if (!pInfo->error && !oldStyleError) {
+ // Return unknown error
+ *outError = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Encountered unknown error during parse"));
+ }
+ return false;
+}
+
+static CFDataRef _createUTF8DataFromString(CFAllocatorRef allocator, CFStringRef str) {
+ CFIndex bytesNeeded = 0;
+ CFStringGetBytes(str, CFRangeMake(0, CFStringGetLength(str)), kCFStringEncodingUTF8, 0, false, NULL, 0, &bytesNeeded);
+
+ const char *bytes = (const char *)CFAllocatorAllocate(allocator, bytesNeeded, 0);
+ CFStringGetBytes(str, CFRangeMake(0, CFStringGetLength(str)), kCFStringEncodingUTF8, 0, false, (uint8_t *)bytes, bytesNeeded, NULL);
+
+ CFDataRef utf8Data = CFDataCreateWithBytesNoCopy(allocator, (const UInt8 *)bytes, bytesNeeded, allocator);
+ return utf8Data;
+}
+
+// Set topLevelKeys to a set of top level keys to decode. If NULL, all keys are decoded. If the top level object is not a dictionary, all objects are decoded. If the plist is not XML, all objects are decoded.
+static Boolean _CFPropertyListCreateWithData(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFErrorRef *outError, Boolean allowNewTypes, CFPropertyListFormat *format, CFSetRef topLevelKeys, CFTypeRef *out) {
+ initStatics();
+ CFStringEncoding encoding;
+
+ if (!data || CFDataGetLength(data) == 0) {
+ if (outError) {
+ *outError = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Cannot parse a NULL or zero-length data"));
}
+ return false;
}
- if (createdBuffer) {
- CFAllocatorDeallocate(kCFAllocatorSystemDefault, (void *)pInfo->begin);
+#if SAVE_PLISTS
+ __savePlistData(data, option);
+#endif
+
+ // Ignore the error from CFTryParseBinaryPlist -- if it doesn't work, we're going to try again anyway using the XML parser
+ if (__CFTryParseBinaryPlist(allocator, data, option, out, NULL)) {
+ if (format) *format = kCFPropertyListBinaryFormat_v1_0;
+ return true;
}
- if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(pInfo->stringSet);
- if (pInfo->error) CFRelease(pInfo->error);
- CFRelease(xmlString);
+
+ // Use our own error variable here so we can check it against NULL later
+ CFErrorRef subError = NULL;
+ CFIndex skip = 0;
+ encoding = encodingForXMLData(data, &subError, &skip); // 0 is an error return, NOT MacRoman.
+
+ if (encoding == 0) {
+ // Couldn't find an encoding
+ // Note that encodingForXMLData() will give us the right values for a standard plist, too.
+ if (outError && subError == NULL) {
+ // encodingForXMLData didn't set an error, so we create a new one here
+ *outError = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Could not determine the encoding of the XML data"));
+ } else if (outError && subError) {
+ // give the caller the subError, they will release
+ *outError = subError;
+ } else if (!outError && subError) {
+ // Release the error
+ CFRelease(subError);
+ }
+ return false;
+ }
+
+ if (encoding == kCFStringEncodingUTF8) {
+ // Use fast path
+ return _CFPropertyListCreateFromUTF8Data(allocator, data, skip, NULL, encoding, option, outError, allowNewTypes, format, topLevelKeys, out);
+ }
+
+ // Convert to UTF8 first
+ CFStringRef xmlString = CFStringCreateWithBytes(allocator, CFDataGetBytePtr(data) + skip, CFDataGetLength(data) - skip, encoding, 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);
+
+ return result;
+}
+
+// -----------------------------------------------------------------------------------------------------------------------
+
+#pragma mark -
+#pragma mark Exported Parsing Functions
+
+CFTypeRef _CFPropertyListCreateFromXMLStringError(CFAllocatorRef allocator, CFStringRef xmlString, CFOptionFlags option, CFErrorRef *error, Boolean allowNewTypes, CFPropertyListFormat *format) {
+ // Convert to UTF8 first
+ 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);
+
return result;
}
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);
+
+// 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) {
+
+ initStatics();
+
+ if (!keyPaths || !data) {
+ return false;
+ }
+
+ uint8_t marker;
+ CFBinaryPlistTrailer trailer;
+ uint64_t offset;
+ const uint8_t *databytes = CFDataGetBytePtr(data);
+ uint64_t datalen = CFDataGetLength(data);
+ Boolean success = false;
+ CFTypeRef out = NULL;
+
+ // First check to see if it is a binary property list
+ if (8 <= datalen && __CFBinaryPlistGetTopLevelInfo(databytes, datalen, &marker, &offset, &trailer)) {
+ uint64_t valueOffset = offset;
+
+ // Split up the key path
+ CFSetRef splitKeyPaths = createTopLevelKeypaths(allocator, keyPaths);
+
+ // Create a dictionary to cache objects in
+ 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);
+ } else {
+ // Try an XML property list
+ success = _CFPropertyListCreateWithData(allocator, data, option, error, true, NULL, keyPaths, &out);
+ }
+
+ if (success && value) {
+ *value = out; // caller releases
+ } else if (out) {
+ CFRelease(out);
+ }
+ return success;
+}
+
/* Get a single value for a given key in a top-level dictionary in a property list.
@param allocator The allocator to use.
@param data The property list data.
uint64_t offset;
const uint8_t *databytes = CFDataGetBytePtr(data);
uint64_t datalen = CFDataGetLength(data);
- bool result = false;
+ Boolean success = false;
// First check to see if it is a binary property list
if (8 <= datalen && __CFBinaryPlistGetTopLevelInfo(databytes, datalen, &marker, &offset, &trailer)) {
for (CFIndex i = 0; i < keyPathCount; i++) {
CFStringRef oneKey = (CFStringRef)CFArrayGetValueAtIndex(keyPathArray, i);
SInt32 intValue = CFStringGetIntValue(oneKey);
- if ((intValue == 0 && CFStringCompare(CFSTR("0"), oneKey, 0) != kCFCompareEqualTo) || intValue == INT_MAX || intValue == INT_MIN) {
+ if ((intValue == 0 && CFStringCompare(CFSTR("0"), oneKey, 0) != kCFCompareEqualTo) || intValue == INT_MAX || intValue == INT_MIN || intValue < 0) {
// Treat as a string key into a dictionary
- result = __CFBinaryPlistGetOffsetForValueFromDictionary3(databytes, datalen, valueOffset, &trailer, (CFTypeRef)oneKey, &keyOffset, &valueOffset, false, objects);
+ success = __CFBinaryPlistGetOffsetForValueFromDictionary3(databytes, datalen, valueOffset, &trailer, (CFTypeRef)oneKey, &keyOffset, &valueOffset, false, objects);
} else {
// Treat as integer index into an array
- result = __CFBinaryPlistGetOffsetForValueFromArray2(databytes, datalen, valueOffset, &trailer, intValue, &valueOffset, objects);
+ success = __CFBinaryPlistGetOffsetForValueFromArray2(databytes, datalen, valueOffset, &trailer, intValue, &valueOffset, objects);
}
- if (!result) {
+ if (!success) {
break;
}
}
// value could be null if the caller wanted to check for the existence of a key but not bother creating it
- if (result && value) {
+ if (success && value) {
CFPropertyListRef pl;
- result = __CFBinaryPlistCreateObject2(databytes, datalen, valueOffset, &trailer, allocator, option, objects, NULL, 0, &pl);
- if (result) {
+ success = __CFBinaryPlistCreateObjectFiltered(databytes, datalen, valueOffset, &trailer, allocator, option, objects, NULL, 0, NULL, &pl);
+ if (success) {
// caller's responsibility to release the created object
*value = pl;
}
// 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;
- result = true;
-
+ CFPropertyListRef nextObject = plist;
+ success = true;
if (!(*error) && plist) {
CFArrayRef keyPathArray = CFStringCreateArrayBySeparatingStrings(kCFAllocatorSystemDefaultGCRefZero, keyPath, CFSTR(":"));
for (CFIndex i = 0; i < CFArrayGetCount(keyPathArray); i++) {
// Treat as integer index into an array
nextObject = (CFPropertyListRef)CFArrayGetValueAtIndex((CFArrayRef)nextObject, intValue);
} else {
- result = false;
+ success = false;
break;
}
}
- if (result && nextObject && value) {
+ if (success && nextObject && value) {
*value = nextObject;
// caller's responsibility to release the created object
CFRetain(*value);
+ } else if (!nextObject) {
+ success = false;
}
if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero)) CFRelease(keyPathArray);
if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(plist);
}
- return result;
+ return success;
}
-CFTypeRef _CFPropertyListCreateWithData(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags option, CFErrorRef *error, Boolean allowNewTypes, CFPropertyListFormat *format) {
- initStatics();
- CFStringEncoding encoding;
- CFPropertyListRef plist;
-
- if (!data || CFDataGetLength(data) == 0) {
- if (error) {
- *error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Cannot parse a NULL or zero-length data"));
- }
- return NULL;
- }
-
-#if SAVE_PLISTS
- __savePlistData(data, option);
-#endif
-
- // Ignore the error from CFTryParseBinaryPlist -- if it doesn't work, we're going to try again anyway using the XML parser
- if (__CFTryParseBinaryPlist(allocator, data, option, &plist, NULL)) {
- if (format) *format = kCFPropertyListBinaryFormat_v1_0;
- return plist;
- }
-
- // Use our own error variable here so we can check it against NULL later
- CFErrorRef subError = NULL;
- encoding = encodingForXMLData(data, &subError); // 0 is an error return, NOT MacRoman.
-
- if (encoding == 0) {
- // Couldn't find an encoding
- // Note that encodingForXMLData() will give us the right values for a standard plist, too.
- if (error && subError == NULL) {
- // encodingForXMLData didn't set an error, so we create a new one here
- *error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Could not determine the encoding of the XML data"));
- } else if (error && subError) {
- // give the caller the subError, they will release
- *error = subError;
- } else if (!error && subError) {
- // Release the error
- CFRelease(subError);
- }
- return NULL;
- }
-
- CFStringRef xmlString = CFStringCreateWithBytes(allocator, CFDataGetBytePtr(data), CFDataGetLength(data), encoding, true);
- if (NULL == xmlString && (!_CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard) || _CFPropertyListAllowNonUTF8)) { // conversion failed, probably because not in proper encoding
- // Call __CFStringCreateImmutableFunnel3() the same way CFStringCreateWithBytes() does, except with the addt'l flag
- if (encoding == kCFStringEncodingUTF8) xmlString = __CFStringCreateImmutableFunnel3(allocator, CFDataGetBytePtr(data), CFDataGetLength(data), kCFStringEncodingUTF8, true, true, false, false, false, (CFAllocatorRef)-1 /* ALLOCATORSFREEFUNC */, kCFStringEncodingLenientUTF8Conversion);
- }
-
- // Haven't done anything XML-specific to this point. However, the encoding we used to translate the bytes should be kept in mind; we used Unicode if the byte-order mark was present; UTF-8 otherwise. If the system encoding is not UTF-8 or some variant of 7-bit ASCII, we'll be in trouble.....
- plist = _CFPropertyListCreateFromXMLStringError(allocator, xmlString, option, error, allowNewTypes, format);
-
- if (xmlString) {
- if (!_CFAllocatorIsGCRefZero(allocator)) CFRelease(xmlString);
- xmlString = NULL;
- }
-
- return plist;
-}
-
-
+// Legacy
CFTypeRef _CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDataRef xmlData, CFOptionFlags option, CFStringRef *errorString, Boolean allowNewTypes, CFPropertyListFormat *format) {
initStatics();
- CFTypeRef result;
+ CFTypeRef out = NULL;
if (errorString) *errorString = NULL;
CFErrorRef error = NULL;
- result = _CFPropertyListCreateWithData(allocator, xmlData, option, &error, allowNewTypes, format);
- if (error && errorString) {
- *errorString = __CFPropertyListCopyErrorDebugDescription(error);
+ Boolean result = _CFPropertyListCreateWithData(allocator, xmlData, option, &error, allowNewTypes, format, NULL, &out);
+ if (!result && error && errorString) {
+ *errorString = __copyErrorDebugDescription(error);
}
if (error) CFRelease(error);
- return result;
+ return out;
}
CFPropertyListRef CFPropertyListCreateWithData(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags options, CFPropertyListFormat *format, CFErrorRef *error) {
initStatics();
CFAssert1(data != NULL, __kCFLogAssertion, "%s(): NULL data not allowed", __PRETTY_FUNCTION__);
CFAssert2(options == kCFPropertyListImmutable || options == kCFPropertyListMutableContainers || options == kCFPropertyListMutableContainersAndLeaves, __kCFLogAssertion, "%s(): Unrecognized option %d", __PRETTY_FUNCTION__, options);
- return _CFPropertyListCreateWithData(allocator, data, options, error, true, format);
+ CFPropertyListRef out = NULL;
+ _CFPropertyListCreateWithData(allocator, data, options, error, true, format, NULL, &out);
+ return out;
}
CFPropertyListRef CFPropertyListCreateFromXMLData(CFAllocatorRef allocator, CFDataRef xmlData, CFOptionFlags option, CFStringRef *errorString) {
CFErrorRef error = NULL;
CFPropertyListRef result = CFPropertyListCreateWithData(allocator, xmlData, option, NULL, &error);
if (error && errorString) {
- *errorString = __CFPropertyListCopyErrorDebugDescription(error);
+ *errorString = __copyErrorDebugDescription(error);
}
if (error) CFRelease(error);
return result;
CFIndex result = CFPropertyListWrite(propertyList, stream, format, 0, &error);
if (error && errorString) {
- *errorString = __CFPropertyListCopyErrorDebugDescription(error);
+ *errorString = __copyErrorDebugDescription(error);
}
if (error) CFRelease(error);
return result;
}
-static void __CFConvertReadStreamToBytes(CFReadStreamRef stream, CFIndex max, uint8_t **buffer, CFIndex *length, CFErrorRef *error) {
+static void __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 (;;) {
CFPropertyListRef CFPropertyListCreateWithStream(CFAllocatorRef allocator, CFReadStreamRef stream, CFIndex streamLength, CFOptionFlags mutabilityOption, CFPropertyListFormat *format, CFErrorRef *error) {
initStatics();
- CFPropertyListRef pl;
- CFDataRef data;
- CFIndex buflen = 0;
- uint8_t *buffer = NULL;
+
CFAssert1(stream != NULL, __kCFLogAssertion, "%s(): NULL stream not allowed", __PRETTY_FUNCTION__);
CFAssert1(CFReadStreamGetTypeID() == CFGetTypeID(stream), __kCFLogAssertion, "%s(): stream argument is not a read stream", __PRETTY_FUNCTION__);
CFAssert1(kCFStreamStatusOpen == CFReadStreamGetStatus(stream) || kCFStreamStatusReading == CFReadStreamGetStatus(stream), __kCFLogAssertion, "%s(): stream is not open", __PRETTY_FUNCTION__);
if (0 == streamLength) streamLength = LONG_MAX;
CFErrorRef underlyingError = NULL;
- __CFConvertReadStreamToBytes(stream, streamLength, &buffer, &buflen, &underlyingError);
+ CFIndex buflen = 0;
+ uint8_t *buffer = NULL;
+ __convertReadStreamToBytes(stream, streamLength, &buffer, &buflen, &underlyingError);
if (underlyingError) {
if (error) {
// Wrap the error from CFReadStream in a new error in the cocoa domain
if (error) *error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("stream had too few bytes"));
return NULL;
}
- data = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, buffer, buflen, kCFAllocatorSystemDefault);
- pl = _CFPropertyListCreateWithData(allocator, data, mutabilityOption, error, true, format);
+
+ CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, buffer, buflen, kCFAllocatorSystemDefault);
+ CFPropertyListRef pl = NULL; // initialize to null, because if the following call fails we must return NULL
+ _CFPropertyListCreateWithData(allocator, data, mutabilityOption, error, true, format, NULL, &pl);
CFRelease(data);
+
return pl;
}
CFErrorRef error = NULL;
CFPropertyListRef result = CFPropertyListCreateWithStream(allocator, stream, length, mutabilityOption, format, &error);
if (error && errorString) {
- *errorString = __CFPropertyListCopyErrorDebugDescription(error);
+ *errorString = __copyErrorDebugDescription(error);
}
if (error) CFRelease(error);
return result;
#endif //DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
-// ========================================================================
-
-//
-// Old NeXT-style property lists
-//
-
-static CFTypeRef parsePlistObject(_CFXMLPlistParseInfo *pInfo, bool requireObject);
-
-#define isValidUnquotedStringCharacter(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || ((x) >= '0' && (x) <= '9') || (x) == '_' || (x) == '$' || (x) == '/' || (x) == ':' || (x) == '.' || (x) == '-')
-
-// Returns true if the advance found something before the end of the buffer, false otherwise
-static Boolean advanceToNonSpace(_CFXMLPlistParseInfo *pInfo) {
- UniChar ch2;
- while (pInfo->curr < pInfo->end) {
- ch2 = *(pInfo->curr);
- pInfo->curr ++;
- if (ch2 >= 9 && ch2 <= 0x0d) continue; // tab, newline, vt, form feed, carriage return
- if (ch2 == ' ' || ch2 == 0x2028 || ch2 == 0x2029) continue; // space and Unicode line sep, para sep
- if (ch2 == '/') {
- if (pInfo->curr >= pInfo->end) {
- // whoops; back up and return
- pInfo->curr --;
- return true;
- } else if (*(pInfo->curr) == '/') {
- pInfo->curr ++;
- while (pInfo->curr < pInfo->end) { // go to end of comment line
- UniChar ch3 = *(pInfo->curr);
- if (ch3 == '\n' || ch3 == '\r' || ch3 == 0x2028 || ch3 == 0x2029) break;
- pInfo->curr ++;
- }
- } else if (*(pInfo->curr) == '*') { // handle /* ... */
- pInfo->curr ++;
- while (pInfo->curr < pInfo->end) {
- ch2 = *(pInfo->curr);
- pInfo->curr ++;
- if (ch2 == '*' && pInfo->curr < pInfo->end && *(pInfo->curr) == '/') {
- pInfo->curr ++; // advance past the '/'
- break;
- }
- }
- } else {
- pInfo->curr --;
- return true;
- }
- } else {
- pInfo->curr --;
- return true;
- }
- }
- return false;
-}
-
-static UniChar getSlashedChar(_CFXMLPlistParseInfo *pInfo) {
- UniChar ch = *(pInfo->curr);
- pInfo->curr ++;
- switch (ch) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': {
- uint8_t num = ch - '0';
- UniChar result;
- CFIndex usedCharLen;
- /* three digits maximum to avoid reading \000 followed by 5 as \5 ! */
- if ((ch = *(pInfo->curr)) >= '0' && ch <= '7') { // we use in this test the fact that the buffer is zero-terminated
- pInfo->curr ++;
- num = (num << 3) + ch - '0';
- if ((pInfo->curr < pInfo->end) && (ch = *(pInfo->curr)) >= '0' && ch <= '7') {
- pInfo->curr ++;
- num = (num << 3) + ch - '0';
- }
- }
- CFStringEncodingBytesToUnicode(kCFStringEncodingNextStepLatin, 0, &num, sizeof(uint8_t), NULL, &result, 1, &usedCharLen);
- return (usedCharLen == 1) ? result : 0;
- }
- case 'U': {
- unsigned num = 0, numDigits = 4; /* Parse four digits */
- while (pInfo->curr < pInfo->end && numDigits--) {
- if (((ch = *(pInfo->curr)) < 128) && isxdigit(ch)) {
- pInfo->curr ++;
- num = (num << 4) + ((ch <= '9') ? (ch - '0') : ((ch <= 'F') ? (ch - 'A' + 10) : (ch - 'a' + 10)));
- }
- }
- return num;
- }
- case 'a': return '\a'; // Note: the meaning of '\a' varies with -traditional to gcc
- case 'b': return '\b';
- case 'f': return '\f';
- case 'n': return '\n';
- case 'r': return '\r';
- case 't': return '\t';
- case 'v': return '\v';
- case '"': return '\"';
- case '\n': return '\n';
- }
- return ch;
-}
-
-static CFStringRef parseQuotedPlistString(_CFXMLPlistParseInfo *pInfo, UniChar quote) {
- CFMutableStringRef str = NULL;
- const UniChar *startMark = pInfo->curr;
- const UniChar *mark = pInfo->curr;
- while (pInfo->curr < pInfo->end) {
- UniChar ch = *(pInfo->curr);
- if (ch == quote) break;
- if (ch == '\\') {
- _catFromMarkToBuf(mark, pInfo->curr, &str, pInfo);
- pInfo->curr ++;
- ch = getSlashedChar(pInfo);
- CFStringAppendCharacters(str, &ch, 1);
- mark = pInfo->curr;
- } else {
- // Note that the original NSParser code was much more complex at this point, but it had to deal with 8-bit characters in a non-UniChar stream. We always have UniChar (we translated the data by the system encoding at the very beginning, hopefully), so this is safe.
- pInfo->curr ++;
- }
- }
- if (pInfo->end <= pInfo->curr) {
- __CFPListRelease(str, pInfo);
- pInfo->curr = startMark;
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unterminated quoted string starting on line %d"), lineNumber(pInfo));
- return NULL;
- }
- if (!str) {
- if (pInfo->mutabilityOption == kCFPropertyListMutableContainersAndLeaves) {
- _catFromMarkToBuf(mark, pInfo->curr, &str, pInfo);
- } else {
- str = (CFMutableStringRef)_uniqueStringForCharacters(pInfo, mark, pInfo->curr-mark);
- }
- } else {
- if (mark != pInfo->curr) {
- _catFromMarkToBuf(mark, pInfo->curr, &str, pInfo);
- }
- if (pInfo->mutabilityOption != kCFPropertyListMutableContainersAndLeaves) {
- CFStringRef uniqueString = _uniqueStringForString(pInfo, str);
- __CFPListRelease(str, pInfo);
- str = (CFMutableStringRef)uniqueString;
- }
- }
- pInfo->curr ++; // Advance past the quote character before returning.
- if (pInfo->error) {
- CFRelease(pInfo->error);
- pInfo->error = NULL;
- }
- return str;
-}
-
-static CFStringRef parseUnquotedPlistString(_CFXMLPlistParseInfo *pInfo) {
- const UniChar *mark = pInfo->curr;
- while (pInfo->curr < pInfo->end) {
- UniChar ch = *pInfo->curr;
- if (isValidUnquotedStringCharacter(ch))
- pInfo->curr ++;
- else break;
- }
- if (pInfo->curr != mark) {
- if (pInfo->mutabilityOption != kCFPropertyListMutableContainersAndLeaves) {
- CFStringRef str = _uniqueStringForCharacters(pInfo, mark, pInfo->curr-mark);
- return str;
- } else {
- CFMutableStringRef str = CFStringCreateMutable(pInfo->allocator, 0);
- CFStringAppendCharacters(str, mark, pInfo->curr - mark);
- return str;
- }
- }
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unexpected EOF"));
- return NULL;
-}
-
-static CFStringRef parsePlistString(_CFXMLPlistParseInfo *pInfo, bool requireObject) {
- UniChar ch;
- Boolean foundChar = advanceToNonSpace(pInfo);
- if (!foundChar) {
- if (requireObject) {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unexpected EOF while parsing string"));
- }
- return NULL;
- }
- ch = *(pInfo->curr);
- if (ch == '\'' || ch == '\"') {
- pInfo->curr ++;
- return parseQuotedPlistString(pInfo, ch);
- } else if (isValidUnquotedStringCharacter(ch)) {
- return parseUnquotedPlistString(pInfo);
- } else {
- if (requireObject) {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Invalid string character at line %d"), lineNumber(pInfo));
- }
- return NULL;
- }
-}
-
-static CFTypeRef parsePlistArray(_CFXMLPlistParseInfo *pInfo) {
- CFMutableArrayRef array = CFArrayCreateMutable(pInfo->allocator, 0, &kCFTypeArrayCallBacks);
- CFTypeRef tmp = parsePlistObject(pInfo, false);
- Boolean foundChar;
- while (tmp) {
- CFArrayAppendValue(array, tmp);
- __CFPListRelease(tmp, pInfo);
- foundChar = advanceToNonSpace(pInfo);
- if (!foundChar) {
- __CFPListRelease(array, pInfo);
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Expected ',' for array at line %d"), lineNumber(pInfo));
- return NULL;
- }
- if (*pInfo->curr != ',') {
- tmp = NULL;
- } else {
- pInfo->curr ++;
- tmp = parsePlistObject(pInfo, false);
- }
- }
- foundChar = advanceToNonSpace(pInfo);
- if (!foundChar || *pInfo->curr != ')') {
- __CFPListRelease(array, pInfo);
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Expected terminating ')' for array at line %d"), lineNumber(pInfo));
- return NULL;
- }
- if (pInfo->error) {
- CFRelease(pInfo->error);
- pInfo->error = NULL;
- }
- pInfo->curr ++;
- return array;
-}
-
-static CFDictionaryRef parsePlistDictContent(_CFXMLPlistParseInfo *pInfo) {
- CFMutableDictionaryRef dict = CFDictionaryCreateMutable(pInfo->allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- CFStringRef key = NULL;
- Boolean failedParse = false;
- key = parsePlistString(pInfo, false);
- while (key) {
- CFTypeRef value;
- Boolean foundChar = advanceToNonSpace(pInfo);
- if (!foundChar) {
- CFLog(kCFLogLevelWarning, CFSTR("CFPropertyListCreateFromXMLData(): Unexpected end of file. Missing semicolon or value in dictionary."));
- failedParse = true;
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Missing ';' on line %d"), lineNumber(pInfo));
- break;
- }
-
- if (*pInfo->curr == ';') {
- /* This is a strings file using the shortcut format */
- /* although this check here really applies to all plists. */
- value = CFRetain(key);
- } else if (*pInfo->curr == '=') {
- pInfo->curr ++;
- value = parsePlistObject(pInfo, true);
- if (!value) {
- failedParse = true;
- break;
- }
- } else {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unexpected ';' or '=' after key at line %d"), lineNumber(pInfo));
- failedParse = true;
- break;
- }
- CFDictionarySetValue(dict, key, value);
- __CFPListRelease(key, pInfo);
- key = NULL;
- __CFPListRelease(value, pInfo);
- value = NULL;
- foundChar = advanceToNonSpace(pInfo);
- if (foundChar && *pInfo->curr == ';') {
- pInfo->curr ++;
- key = parsePlistString(pInfo, false);
- } else if (true || !foundChar) {
- CFLog(kCFLogLevelWarning, CFSTR("CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary."));
- failedParse = true;
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Missing ';' on line %d"), lineNumber(pInfo));
- }
- }
-
- if (failedParse) {
- __CFPListRelease(key, pInfo);
- __CFPListRelease(dict, pInfo);
- return NULL;
- }
- if (pInfo->error) {
- CFRelease(pInfo->error);
- pInfo->error = NULL;
- }
- return dict;
-}
-
-static CFTypeRef parsePlistDict(_CFXMLPlistParseInfo *pInfo) {
- CFDictionaryRef dict = parsePlistDictContent(pInfo);
- if (!dict) return NULL;
- Boolean foundChar = advanceToNonSpace(pInfo);
- if (!foundChar || *pInfo->curr != '}') {
- __CFPListRelease(dict, pInfo);
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Expected terminating '}' for dictionary at line %d"), lineNumber(pInfo));
- return NULL;
- }
- pInfo->curr ++;
- return dict;
-}
-
-CF_INLINE unsigned char fromHexDigit(unsigned char ch) {
- if (isdigit(ch)) return ch - '0';
- if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10;
- if ((ch >= 'A') && (ch <= 'F')) return ch - 'A' + 10;
- return 0xff; // Just choose a large number for the error code
-}
-
-/* Gets up to bytesSize bytes from a plist data. Returns number of bytes actually read. Leaves cursor at first non-space, non-hex character.
- -1 is returned for unexpected char, -2 for uneven number of hex digits
-*/
-static int getDataBytes(_CFXMLPlistParseInfo *pInfo, unsigned char *bytes, int bytesSize) {
- int numBytesRead = 0;
- while ((pInfo->curr < pInfo->end) && (numBytesRead < bytesSize)) {
- int first, second;
- UniChar ch1 = *pInfo->curr;
- if (ch1 == '>') return numBytesRead; // Meaning we're done
- first = fromHexDigit((unsigned char)ch1);
- if (first != 0xff) { // If the first char is a hex, then try to read a second hex
- pInfo->curr++;
- if (pInfo->curr >= pInfo->end) return -2; // Error: uneven number of hex digits
- UniChar ch2 = *pInfo->curr;
- second = fromHexDigit((unsigned char)ch2);
- if (second == 0xff) return -2; // Error: uneven number of hex digits
- bytes[numBytesRead++] = (first << 4) + second;
- pInfo->curr++;
- } else if (ch1 == ' ' || ch1 == '\n' || ch1 == '\t' || ch1 == '\r' || ch1 == 0x2028 || ch1 == 0x2029) {
- pInfo->curr++;
- } else {
- return -1; // Error: unexpected character
- }
- }
- return numBytesRead; // This does likely mean we didn't encounter a '>', but we'll let the caller deal with that
-}
-
-#define numBytes 400
-static CFTypeRef parsePlistData(_CFXMLPlistParseInfo *pInfo) {
- CFMutableDataRef result = CFDataCreateMutable(pInfo->allocator, 0);
-
- // Read hex bytes and append them to result
- while (1) {
- unsigned char bytes[numBytes];
- int numBytesRead = getDataBytes(pInfo, bytes, numBytes);
- if (numBytesRead < 0) {
- __CFPListRelease(result, pInfo);
- switch (numBytesRead) {
- case -2:
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Malformed data byte group at line %d; uneven length"), lineNumber(pInfo));
- break;
- default:
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Malformed data byte group at line %d; invalid hex"), lineNumber(pInfo));
- break;
- }
- return NULL;
- }
- if (numBytesRead == 0) break;
- CFDataAppendBytes(result, bytes, numBytesRead);
- }
-
- if (pInfo->error) {
- CFRelease(pInfo->error);
- pInfo->error = NULL;
- }
-
- if (*(pInfo->curr) == '>') {
- pInfo->curr ++; // Move past '>'
- return result;
- } else {
- __CFPListRelease(result, pInfo);
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Expected terminating '>' for data at line %d"), lineNumber(pInfo));
- return NULL;
- }
-}
-#undef numBytes
-
-// Returned object is retained; caller must free.
-static CFTypeRef parsePlistObject(_CFXMLPlistParseInfo *pInfo, bool requireObject) {
- UniChar ch;
- Boolean foundChar = advanceToNonSpace(pInfo);
- if (!foundChar) {
- if (requireObject) {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unexpected EOF while parsing plist"));
- }
- return NULL;
- }
- ch = *(pInfo->curr);
- pInfo->curr ++;
- if (ch == '{') {
- return parsePlistDict(pInfo);
- } else if (ch == '(') {
- return parsePlistArray(pInfo);
- } else if (ch == '<') {
- return parsePlistData(pInfo);
- } else if (ch == '\'' || ch == '\"') {
- return parseQuotedPlistString(pInfo, ch);
- } else if (isValidUnquotedStringCharacter(ch)) {
- pInfo->curr --;
- return parseUnquotedPlistString(pInfo);
- } else {
- pInfo->curr --; // Must back off the charcter we just read
- if (requireObject) {
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Unexpected character '0x%x' at line %d"), ch, lineNumber(pInfo));
- }
- return NULL;
- }
-}
-
-static CFTypeRef parseOldStylePropertyListOrStringsFile(_CFXMLPlistParseInfo *pInfo) {
- const UniChar *begin = pInfo->curr;
- CFTypeRef result;
- Boolean foundChar = advanceToNonSpace(pInfo);
- // A file consisting only of whitespace (or empty) is now defined to be an empty dictionary
- if (!foundChar) return CFDictionaryCreateMutable(pInfo->allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- result = parsePlistObject(pInfo, true);
- foundChar = advanceToNonSpace(pInfo);
- if (!foundChar) return result;
- if (!result) return NULL;
- if (CFGetTypeID(result) != stringtype) {
- __CFPListRelease(result, pInfo);
- pInfo->error = __CFPropertyListCreateError(kCFPropertyListReadCorruptError, CFSTR("Junk after plist at line %d"), lineNumber(pInfo));
- return NULL;
- }
- __CFPListRelease(result, pInfo);
- // Check for a strings file (looks like a dictionary without the opening/closing curly braces)
- pInfo->curr = begin;
- return parsePlistDictContent(pInfo);
-}
-
-#undef isValidUnquotedStringCharacter
+#pragma mark -
+#pragma mark Property List Copies
static CFArrayRef _arrayDeepImmutableCopy(CFAllocatorRef allocator, CFArrayRef array, CFOptionFlags mutabilityOption) {
CFArrayRef result = NULL;
*/
/* CFPropertyList.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFPROPERTYLIST__)
#include <CoreFoundation/CFStream.h>
#endif
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFPropertyListMutabilityOptions) {
kCFPropertyListImmutable = 0,
kCFPropertyListMutableContainers,
kCFPropertyListMutableContainersAndLeaves
};
-typedef CFOptionFlags CFPropertyListMutabilityOptions;
+
+CF_IMPLICIT_BRIDGING_DISABLED
/*
Creates a property list object from its XML description; xmlData should
CF_EXPORT
CFDataRef CFPropertyListCreateXMLData(CFAllocatorRef allocator, CFPropertyListRef propertyList);
+CF_IMPLICIT_BRIDGING_ENABLED
+
/*
Recursively creates a copy of the given property list (so nested arrays
and dictionaries are copied as well as the top-most container). The
CF_EXPORT
CFPropertyListRef CFPropertyListCreateDeepCopy(CFAllocatorRef allocator, CFPropertyListRef propertyList, CFOptionFlags mutabilityOption);
-enum {
+typedef CF_ENUM(CFIndex, CFPropertyListFormat) {
kCFPropertyListOpenStepFormat = 1,
kCFPropertyListXMLFormat_v1_0 = 100,
kCFPropertyListBinaryFormat_v1_0 = 200
};
-typedef CFIndex CFPropertyListFormat;
/* Returns true if the object graph rooted at plist is a valid property list
* graph -- that is, no cycles, containing only plist objects, and dictionary
Boolean CFPropertyListIsValid(CFPropertyListRef plist, CFPropertyListFormat format);
#if TARGET_OS_MAC || TARGET_OS_WIN32 || TARGET_OS_EMBEDDED
+CF_IMPLICIT_BRIDGING_DISABLED
/* Writes the bytes of a plist serialization out to the stream. The
* stream must be opened and configured -- the function simply writes
CF_EXPORT
CFPropertyListRef CFPropertyListCreateFromStream(CFAllocatorRef allocator, CFReadStreamRef stream, CFIndex streamLength, CFOptionFlags mutabilityOption, CFPropertyListFormat *format, CFStringRef *errorString);
+CF_IMPLICIT_BRIDGING_ENABLED
#endif
-#if MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED || __IPHONE_4_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED
+CF_IMPLICIT_BRIDGING_DISABLED
+
enum {
kCFPropertyListReadCorruptError = 3840, // Error parsing a property list
kCFPropertyListReadUnknownVersionError = 3841, // The version number in the property list is unknown
kCFPropertyListReadStreamError = 3842, // Stream error reading a property list
kCFPropertyListWriteStreamError = 3851, // Stream error writing a property list
-};
-#endif
+} CF_ENUM_AVAILABLE(10_6, 4_0);
/* Create a property list with a CFData input. If the format parameter is non-NULL, it will be set to the format of the data after parsing is complete. The options parameter is used to specify CFPropertyListMutabilityOptions. If an error occurs while parsing the data, the return value will be NULL. Additionally, if an error occurs and the error parameter is non-NULL, the error parameter will be set to a CFError describing the problem, which the caller must release. If the parse succeeds, the returned value is a reference to the new property list. It is the responsibility of the caller to release this value.
*/
CF_EXPORT
CFDataRef CFPropertyListCreateData(CFAllocatorRef allocator, CFPropertyListRef propertyList, CFPropertyListFormat format, CFOptionFlags options, CFErrorRef *error) CF_AVAILABLE(10_6, 4_0);
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFPROPERTYLIST__ */
*/
/* CFRunLoop.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Tony Parker
*/
#include <limits.h>
#include <pthread.h>
#include <dispatch/dispatch.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
+#include <dispatch/private.h>
#include <CoreFoundation/CFUserNotification.h>
#include <mach/mach.h>
#include <mach/clock_types.h>
#include <dlfcn.h>
extern mach_port_t _dispatch_get_main_queue_port_4CF(void);
extern void _dispatch_main_queue_callback_4CF(mach_msg_header_t *msg);
-#else
+#elif DEPLOYMENT_TARGET_WINDOWS
#include <process.h>
-__private_extern__ LONGLONG __CFTSRToFiletime(int64_t tsr);
DISPATCH_EXPORT HANDLE _dispatch_get_main_queue_handle_4CF(void);
DISPATCH_EXPORT void _dispatch_main_queue_callback_4CF(void);
+
+#define MACH_PORT_NULL 0
+#define mach_port_name_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
#include <Block.h>
+
static int _LogCFRunLoop = 0;
// for conservative arithmetic safety, such that (TIMER_DATE_LIMIT + TIMER_INTERVAL_LIMIT + kCFAbsoluteTimeIntervalSince1970) * 10^9 < 2^63
static pthread_t kNilPthreadT = { nil, nil };
#define pthreadPointer(a) a.p
+typedef int kern_return_t;
+#define KERN_SUCCESS 0
#else
// 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
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
__private_extern__ uint32_t __CFGetProcessPortCount(void) {
ipc_info_space_t info;
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) HALT;
+ if (ret != KERN_SUCCESS) {
+ char msg[256];
+ snprintf(msg, 256, "*** Failure from thread_resume (%d) ***", ret);
+ CRSetCrashLogMessage(msg);
+ HALT;
+ }
mach_port_deallocate(mach_task_self(), thread);
}
}
static __CFPort __CFPortAllocate(void) {
__CFPort result = CFPORT_NULL;
- kern_return_t ret;
- ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &result);
- if (KERN_SUCCESS == ret) {
- ret = mach_port_insert_right(mach_task_self(), result, result, MACH_MSG_TYPE_MAKE_SEND);
- } else {
- __THE_SYSTEM_HAS_NO_PORTS_AVAILABLE__(ret);
- }
- if (KERN_SUCCESS == 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);
+ kern_return_t ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &result);
+ 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;
+ }
+
+ 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;
+ }
+
+ 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) mach_port_destroy(mach_task_self(), result);
- return (KERN_SUCCESS == ret) ? result : CFPORT_NULL;
+
+ return result;
}
CF_INLINE void __CFPortFree(__CFPort port) {
return (KERN_SUCCESS == ret) ? result : CFPORT_NULL;
}
-CF_INLINE Boolean __CFPortSetInsert(__CFPort port, __CFPortSet portSet) {
+CF_INLINE kern_return_t __CFPortSetInsert(__CFPort port, __CFPortSet portSet) {
if (MACH_PORT_NULL == port) {
- return false;
+ return -1;
}
- kern_return_t ret = mach_port_insert_member(mach_task_self(), port, portSet);
- return (KERN_SUCCESS == ret);
+ return mach_port_insert_member(mach_task_self(), port, portSet);
}
-CF_INLINE Boolean __CFPortSetRemove(__CFPort port, __CFPortSet portSet) {
+CF_INLINE kern_return_t __CFPortSetRemove(__CFPort port, __CFPortSet portSet) {
if (MACH_PORT_NULL == port) {
- return false;
+ return -1;
}
- kern_return_t ret = mach_port_extract_member(mach_task_self(), port, portSet);
- return (KERN_SUCCESS == ret);
+ return mach_port_extract_member(mach_task_self(), port, portSet);
}
CF_INLINE void __CFPortSetFree(__CFPortSet portSet) {
return result;
}
-static Boolean __CFPortSetInsert(__CFPort port, __CFPortSet portSet) {
+static kern_return_t __CFPortSetInsert(__CFPort port, __CFPortSet portSet) {
if (NULL == port) {
- return false;
+ return -1;
}
__CFSpinLock(&(portSet->lock));
if (portSet->used >= portSet->size) {
}
portSet->handles[portSet->used++] = port;
__CFSpinUnlock(&(portSet->lock));
- return true;
+ return KERN_SUCCESS;
}
-static Boolean __CFPortSetRemove(__CFPort port, __CFPortSet portSet) {
+static kern_return_t __CFPortSetRemove(__CFPort port, __CFPortSet portSet) {
int i, j;
if (NULL == port) {
- return false;
+ return -1;
}
__CFSpinLock(&(portSet->lock));
for (i = 0; i < portSet->used; i++) {
}
}
__CFSpinUnlock(&(portSet->lock));
- return false;
+ return KERN_SUCCESS;
}
#endif
typedef UnsignedWide AbsoluteTime;
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
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);
if (result == MACH_SEND_TIMED_OUT) mach_msg_destroy(&header);
return result;
}
+#elif DEPLOYMENT_TARGET_WINDOWS
+
+static HANDLE mk_timer_create(void) {
+ return CreateWaitableTimer(NULL, FALSE, NULL);
+}
+
+static kern_return_t mk_timer_destroy(HANDLE name) {
+ BOOL res = CloseHandle(name);
+ if (!res) {
+ DWORD err = GetLastError();
+ CFLog(kCFLogLevelError, CFSTR("CFRunLoop: Unable to destroy timer: %d"), err);
+ }
+ return (int)res;
+}
+
+static kern_return_t mk_timer_arm(HANDLE name, LARGE_INTEGER expire_time) {
+ BOOL res = SetWaitableTimer(name, &expire_time, 0, NULL, NULL, FALSE);
+ if (!res) {
+ DWORD err = GetLastError();
+ CFLog(kCFLogLevelError, CFSTR("CFRunLoop: Unable to set timer: %d"), err);
+ }
+ return (int)res;
+}
+
+static kern_return_t mk_timer_cancel(HANDLE name, LARGE_INTEGER *result_time) {
+ BOOL res = CancelWaitableTimer(name);
+ if (!res) {
+ DWORD err = GetLastError();
+ CFLog(kCFLogLevelError, CFSTR("CFRunLoop: Unable to cancel timer: %d"), err);
+ }
+ return (int)res;
+}
+
+// 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) {
+ 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) {
+ result.QuadPart = 0;
+ } else {
+ CFTimeInterval amountOfTimeToWait = __CFTSRToTimeInterval(timeDiff);
+ // Result is in 100 ns (10**-7 sec) units to be consistent with a FILETIME.
+ // CFTimeInterval is in seconds.
+ result.QuadPart = -(amountOfTimeToWait * 10000000);
+ }
+ return result;
+}
+
#endif
/* unlock a run loop and modes before doing callouts/sleeping */
CFMutableDictionaryRef _portToV1SourceMap;
__CFPortSet _portSet;
CFIndex _observerMask;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
mach_port_t _timerPort;
#endif
#if DEPLOYMENT_TARGET_WINDOWS
if (NULL != rlm->_portToV1SourceMap) CFRelease(rlm->_portToV1SourceMap);
CFRelease(rlm->_name);
__CFPortSetFree(rlm->_portSet);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if (MACH_PORT_NULL != rlm->_timerPort) mk_timer_destroy(rlm->_timerPort);
-#elif DEPLOYMENT_TARGET_WINDOWS
- if (NULL != rlm->_timerPort) CloseHandle(rlm->_timerPort);
-#endif
pthread_mutex_destroy(&rlm->_lock);
memset((char *)cf + sizeof(CFRuntimeBase), 0x7C, sizeof(struct __CFRunLoopMode) - sizeof(CFRuntimeBase));
}
void (^_block)(void);
};
+typedef struct _per_run_data {
+ uint32_t a;
+ uint32_t b;
+ uint32_t stopped;
+ uint32_t ignoreWakeUps;
+} _per_run_data;
+
struct __CFRunLoop {
CFRuntimeBase _base;
pthread_mutex_t _lock; /* locked for accessing mode list */
__CFPort _wakeUpPort; // used for CFRunLoopWakeUp
- Boolean _ignoreWakeUps;
- volatile uint32_t *_stopped;
+ Boolean _unused;
+ volatile _per_run_data *_perRunData; // reset for runs of the run loop
pthread_t _pthread;
uint32_t _winthread;
CFMutableSetRef _commonModes;
CFTypeRef _counterpart;
};
-#if DEPLOYMENT_TARGET_WINDOWS
-static Boolean __CFRunLoopDoSource1(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLoopSourceRef rls);
-#endif
-
/* Bit 0 of the base reserved bits is used for stopped state */
/* Bit 1 of the base reserved bits is used for sleeping state */
/* Bit 2 of the base reserved bits is used for deallocating state */
+CF_INLINE volatile _per_run_data *__CFRunLoopPushPerRunData(CFRunLoopRef rl) {
+ volatile _per_run_data *previous = rl->_perRunData;
+ rl->_perRunData = (volatile _per_run_data *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(_per_run_data), 0);
+ rl->_perRunData->a = 0x4346524C;
+ rl->_perRunData->b = 0x4346524C; // 'CFRL'
+ rl->_perRunData->stopped = 0x00000000;
+ rl->_perRunData->ignoreWakeUps = 0x00000000;
+ return previous;
+}
+
+CF_INLINE void __CFRunLoopPopPerRunData(CFRunLoopRef rl, volatile _per_run_data *previous) {
+ if (rl->_perRunData) CFAllocatorDeallocate(kCFAllocatorSystemDefault, (void *)rl->_perRunData);
+ rl->_perRunData = previous;
+}
+
CF_INLINE Boolean __CFRunLoopIsStopped(CFRunLoopRef rl) {
- return (rl->_stopped && rl->_stopped[2]) ? true : false;
+ return (rl->_perRunData->stopped) ? true : false;
}
CF_INLINE void __CFRunLoopSetStopped(CFRunLoopRef rl) {
- if (!rl->_stopped) {
- rl->_stopped = (uint32_t volatile *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 4 * sizeof(uint32_t), 0);
- rl->_stopped[0] = 0x4346524C;
- rl->_stopped[1] = 0x4346524C; // 'CFRL'
- rl->_stopped[2] = 0x00000000; // here the value is stored
- rl->_stopped[3] = 0x4346524C;
- }
- if (rl->_stopped) rl->_stopped[2] = 0x53544F50; // 'STOP'
+ rl->_perRunData->stopped = 0x53544F50; // 'STOP'
}
CF_INLINE void __CFRunLoopUnsetStopped(CFRunLoopRef rl) {
- if (rl->_stopped) rl->_stopped[2] = 0x0;
+ rl->_perRunData->stopped = 0x0;
+}
+
+CF_INLINE Boolean __CFRunLoopIsIgnoringWakeUps(CFRunLoopRef rl) {
+ return (rl->_perRunData->ignoreWakeUps) ? true : false;
+}
+
+CF_INLINE void __CFRunLoopSetIgnoreWakeUps(CFRunLoopRef rl) {
+ rl->_perRunData->ignoreWakeUps = 0x57414B45; // 'WAKE'
+}
+
+CF_INLINE void __CFRunLoopUnsetIgnoreWakeUps(CFRunLoopRef rl) {
+ rl->_perRunData->ignoreWakeUps = 0x0;
}
CF_INLINE Boolean __CFRunLoopIsSleeping(CFRunLoopRef rl) {
CFMutableStringRef result;
result = CFStringCreateMutable(kCFAllocatorSystemDefault, 0);
#if DEPLOYMENT_TARGET_WINDOWS
- CFStringAppendFormat(result, NULL, CFSTR("<CFRunLoop %p [%p]>{wakeup port = 0x%x, stopped = %s,\ncurrent mode = %@,\n"), cf, CFGetAllocator(cf), rl->_wakeUpPort, (rl->_stopped && *(rl->_stopped)) ? "true" : "false", rl->_currentMode ? rl->_currentMode->_name : CFSTR("(none)"));
+ CFStringAppendFormat(result, NULL, CFSTR("<CFRunLoop %p [%p]>{wakeup port = 0x%x, stopped = %s, ignoreWakeUps = %s, \ncurrent mode = %@,\n"), cf, CFGetAllocator(cf), rl->_wakeUpPort, __CFRunLoopIsStopped(rl) ? "true" : "false", __CFRunLoopIsIgnoringWakeUps(rl) ? "true" : "false", rl->_currentMode ? rl->_currentMode->_name : CFSTR("(none)"));
#else
- CFStringAppendFormat(result, NULL, CFSTR("<CFRunLoop %p [%p]>{wakeup port = 0x%x, stopped = %s,\ncurrent mode = %@,\n"), cf, CFGetAllocator(cf), rl->_wakeUpPort, (rl->_stopped && (rl->_stopped[2] == 0x53544F50)) ? "true" : "false", rl->_currentMode ? rl->_currentMode->_name : CFSTR("(none)"));
+ CFStringAppendFormat(result, NULL, CFSTR("<CFRunLoop %p [%p]>{wakeup port = 0x%x, stopped = %s, ignoreWakeUps = %s, \ncurrent mode = %@,\n"), cf, CFGetAllocator(cf), rl->_wakeUpPort, __CFRunLoopIsStopped(rl) ? "true" : "false", __CFRunLoopIsIgnoringWakeUps(rl) ? "true" : "false", rl->_currentMode ? rl->_currentMode->_name : CFSTR("(none)"));
#endif
CFStringAppendFormat(result, NULL, CFSTR("common modes = %@,\ncommon mode items = %@,\nmodes = %@}\n"), rl->_commonModes, rl->_commonModeItems, rl->_modes);
return result;
rlm->_timers = NULL;
rlm->_observerMask = 0;
rlm->_portSet = __CFPortSetAllocate();
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
rlm->_timerPort = mk_timer_create();
-#elif DEPLOYMENT_TARGET_WINDOWS
- // We use a manual reset timer because it is possible that we will WaitForMultipleObjectsEx on the timer port but not service it on that run loop iteration. The event is reset when we handle the timers.
- rlm->_timerPort = CreateWaitableTimer(NULL, TRUE, NULL);
-#endif
- if (!__CFPortSetInsert(rlm->_timerPort, rlm->_portSet)) HALT;
- if (!__CFPortSetInsert(rl->_wakeUpPort, rlm->_portSet)) HALT;
+ 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(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
rlm->_msgQMask = 0;
rlm->_msgPump = NULL;
}
__CFPortFree(rl->_wakeUpPort);
rl->_wakeUpPort = CFPORT_NULL;
+ __CFRunLoopPopPerRunData(rl, NULL);
__CFRunLoopUnlock(rl);
pthread_mutex_destroy(&rl->_lock);
memset((char *)cf + sizeof(CFRuntimeBase), 0x8C, sizeof(struct __CFRunLoop) - sizeof(CFRuntimeBase));
if (NULL == loop) {
return NULL;
}
- loop->_stopped = NULL;
+ (void)__CFRunLoopPushPerRunData(loop);
__CFRunLoopLockInit(&loop->_lock);
loop->_wakeUpPort = __CFPortAllocate();
if (CFPORT_NULL == loop->_wakeUpPort) HALT;
- loop->_ignoreWakeUps = true;
+ __CFRunLoopSetIgnoreWakeUps(loop);
loop->_commonModes = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks);
CFSetAddValue(loop->_commonModes, kCFRunLoopDefaultMode);
loop->_commonModeItems = NULL;
__CFSpinLock(&loopsLock);
}
CFRunLoopRef loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
+ __CFSpinUnlock(&loopsLock);
if (!loop) {
- __CFSpinUnlock(&loopsLock);
CFRunLoopRef newLoop = __CFRunLoopCreate(t);
__CFSpinLock(&loopsLock);
loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t));
CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop);
loop = newLoop;
}
+ // don't release run loops inside the loopsLock, because CFRunLoopDeallocate may end up taking it
+ __CFSpinUnlock(&loopsLock);
CFRelease(newLoop);
}
if (pthread_equal(t, pthread_self())) {
_CFSetTSD(__CFTSDKeyRunLoopCntr, (void *)(PTHREAD_DESTRUCTOR_ITERATIONS-1), (void (*)(void *))__CFFinalizeRunLoop);
}
}
- __CFSpinUnlock(&loopsLock);
return loop;
}
static void __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__() __attribute__((noinline));
static void __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__(
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
void *(*perform)(void *msg, CFIndex size, CFAllocatorRef allocator, void *info),
mach_msg_header_t *msg, CFIndex size, mach_msg_header_t **reply,
#else
#endif
void *info) {
if (perform) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
*reply = perform(msg, size, kCFAllocatorSystemDefault, info);
#else
perform(info);
// msg, size and reply are unused on Windows
static Boolean __CFRunLoopDoSource1() __attribute__((noinline));
static Boolean __CFRunLoopDoSource1(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFRunLoopSourceRef rls
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
, mach_msg_header_t *msg, CFIndex size, mach_msg_header_t **reply
#endif
) { /* DOES CALLOUT */
__CFRunLoopSourceUnsetSignaled(rls);
__CFRunLoopSourceUnlock(rls);
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__(rls->_context.version1.perform,
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
msg, size, reply,
#endif
rls->_context.version1.info);
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;
+ }
+ }
+ if (nextTimer) {
+ int64_t fireTSR = nextTimer->_fireTSR;
+ fireTSR = (fireTSR / tenus + 1) * tenus;
+ mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime(fireTSR));
+ }
+}
+
// 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 (!found && isInArray) return;
CFIndex newIdx = __CFRunLoopInsertionIndexInTimerArray(rlm->_timers, rlt);
CFArrayInsertValueAtIndex(rlm->_timers, newIdx, rlt);
- 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;
- }
- }
- if (nextTimer) {
- int64_t fireTSR = nextTimer->_fireTSR;
- fireTSR = (fireTSR / tenus + 1) * tenus;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
- mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime(fireTSR));
-#elif DEPLOYMENT_TARGET_WINDOWS
- LARGE_INTEGER dueTime;
- dueTime.QuadPart = __CFTSRToFiletime(fireTSR);
- SetWaitableTimer(rlm->_timerPort, &dueTime, 0, NULL, NULL, FALSE);
-#endif
- }
+ __CFArmNextTimerInMode(rlm);
if (isInArray) CFRelease(rlt);
}
oldFireTSR = rlt->_fireTSR;
__CFRunLoopTimerFireTSRUnlock();
- 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;
- }
- }
- if (nextTimer) {
- int64_t fireTSR = nextTimer->_fireTSR;
- fireTSR = (fireTSR / tenus + 1) * tenus;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
- mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime(fireTSR));
-#elif DEPLOYMENT_TARGET_WINDOWS
- LARGE_INTEGER dueTime;
- dueTime.QuadPart = __CFTSRToFiletime(fireTSR);
- SetWaitableTimer(rlm->_timerPort, &dueTime, 0, NULL, NULL, FALSE);
-#endif
- }
+ __CFArmNextTimerInMode(rlm);
__CFRunLoopModeUnlock(rlm);
__CFRunLoopUnlock(rl);
// 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.
- 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;
- }
- }
- if (nextTimer) {
- int64_t fireTSR = nextTimer->_fireTSR;
- fireTSR = (fireTSR / tenus + 1) * tenus;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
- mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime(fireTSR));
-#else
- LARGE_INTEGER dueTime;
- dueTime.QuadPart = __CFTSRToFiletime(fireTSR);
- SetWaitableTimer(rlm->_timerPort, &dueTime, 0, NULL, NULL, FALSE);
-#endif
- }
+ __CFArmNextTimerInMode(rlm);
} else {
int64_t nextFireTSR = 0LL;
int64_t intervalTSR = 0LL;
static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode) __attribute__((noinline));
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#define TIMEOUT_INFINITY (~(mach_msg_timeout_t)0)
// The interval is DISPATCH_TIME_FOREVER, so this won't fire again
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#elif DEPLOYMENT_TARGET_WINDOWS
-#define MACH_PORT_NULL 0
-#define mach_port_name_t HANDLE
-#define _dispatch_get_main_queue_port_4CF _dispatch_get_main_queue_handle_4CF
-#else
-#error Unknown deployment target - CFRunLoop not functional
-#endif
-
/* 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();
rlm->_stopped = false;
return kCFRunLoopRunStopped;
}
-
+
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();
int32_t retVal = 0;
do {
uint8_t msg_buffer[3 * 1024];
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
mach_msg_header_t *msg = NULL;
#elif DEPLOYMENT_TARGET_WINDOWS
HANDLE livePort = NULL;
#endif
__CFPortSet waitSet = rlm->_portSet;
- rl->_ignoreWakeUps = false;
+ __CFRunLoopUnsetIgnoreWakeUps(rl);
if (rlm->_observerMask & kCFRunLoopBeforeTimers) __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeTimers);
if (rlm->_observerMask & kCFRunLoopBeforeSources) __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);
Boolean poll = sourceHandledThisLoop || (0LL == timeout_context->termTSR);
if (MACH_PORT_NULL != dispatchPort && !didDispatchPortLastTime) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#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)) {
goto handle_msg;
// want these ports to get serviced.
__CFPortSetInsert(dispatchPort, waitSet);
-
+
__CFRunLoopModeUnlock(rlm);
__CFRunLoopUnlock(rl);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (kCFUseCollectableAllocator) {
objc_clear_stack(0);
memset(msg_buffer, 0, sizeof(msg_buffer));
__CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), poll ? 0 : TIMEOUT_INFINITY);
#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.
- // Note: don't pass 0 for polling, or this thread will never yield the CPU.
__CFRunLoopWaitForMultipleObjects(waitSet, NULL, poll ? 0 : TIMEOUT_INFINITY, rlm->_msgQMask, &livePort, &windowsMessageReceived);
#endif
// in there if this function returns.
__CFPortSetRemove(dispatchPort, waitSet);
-
- rl->_ignoreWakeUps = true;
+
+ __CFRunLoopSetIgnoreWakeUps(rl);
// user callouts now OK again
__CFRunLoopUnsetSleeping(rl);
if (!poll && (rlm->_observerMask & kCFRunLoopAfterWaiting)) __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);
handle_msg:;
- rl->_ignoreWakeUps = true;
+ __CFRunLoopSetIgnoreWakeUps(rl);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#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
__CFRunLoopLock(rl);
__CFRunLoopModeLock(rlm);
sourceHandledThisLoop = true;
- } else
+
+ // To prevent starvation of sources other than the message queue, we check again to see if any other sources need to be serviced
+ // Use 0 for the mask so windows messages are ignored this time. Also use 0 for the timeout, because we're just checking to see if the things are signalled right now -- we will wait on them again later.
+ // NOTE: Ignore the dispatch source (it's not in the wait set anymore) and also don't run the observers here since we are polling.
+ __CFRunLoopSetSleeping(rl);
+ __CFRunLoopModeUnlock(rlm);
+ __CFRunLoopUnlock(rl);
+
+ __CFRunLoopWaitForMultipleObjects(waitSet, NULL, 0, 0, &livePort, NULL);
+
+ __CFRunLoopLock(rl);
+ __CFRunLoopModeLock(rlm);
+ __CFRunLoopUnsetSleeping(rl);
+ // If we have a new live port then it will be handled below as normal
+ }
+
+
#endif
if (MACH_PORT_NULL == livePort) {
// handle nothing
#endif
} else if (livePort == rlm->_timerPort) {
#if DEPLOYMENT_TARGET_WINDOWS
- // We use a manual reset timer to ensure that we don't miss timers firing because the run loop did the wakeUpPort this time
- // The only way to reset a timer is to reset the timer using SetWaitableTimer. We don't want it to fire again though, so we set the timeout to a large negative value. The timer may be reset again inside the timer handling code.
- LARGE_INTEGER dueTime;
- dueTime.QuadPart = LONG_MIN;
- SetWaitableTimer(rlm->_timerPort, &dueTime, 0, NULL, NULL, FALSE);
+ // 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.
+ // 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);
+ }
+#else
+ __CFRunLoopDoTimers(rl, rlm, mach_absolute_time());
#endif
- __CFRunLoopDoTimers(rl, rlm, mach_absolute_time());
} else if (livePort == dispatchPort) {
- __CFRunLoopModeUnlock(rlm);
- __CFRunLoopUnlock(rl);
+ __CFRunLoopModeUnlock(rlm);
+ __CFRunLoopUnlock(rl);
_CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)6, NULL);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
- _dispatch_main_queue_callback_4CF(msg);
-#elif DEPLOYMENT_TARGET_WINDOWS
- _dispatch_main_queue_callback_4CF();
-#endif
+ _dispatch_main_queue_callback_4CF(msg);
_CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)0, NULL);
- __CFRunLoopLock(rl);
- __CFRunLoopModeLock(rlm);
- sourceHandledThisLoop = true;
+ __CFRunLoopLock(rl);
+ __CFRunLoopModeLock(rlm);
+ sourceHandledThisLoop = true;
didDispatchPortLastTime = true;
} else {
// Despite the name, this works for windows handles as well
CFRunLoopSourceRef rls = __CFRunLoopModeFindSourceForMachPort(rl, rlm, livePort);
if (rls) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
mach_msg_header_t *reply = NULL;
sourceHandledThisLoop = __CFRunLoopDoSource1(rl, rlm, rls, msg, msg->msgh_size, &reply) || sourceHandledThisLoop;
if (NULL != reply) {
#endif
}
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (msg && msg != (mach_msg_header_t *)msg_buffer) free(msg);
#endif
__CFRunLoopUnlock(rl);
return did ? kCFRunLoopRunHandledSource : kCFRunLoopRunFinished;
}
- uint32_t *previousStopped = (uint32_t *)rl->_stopped;
- rl->_stopped = NULL;
+ volatile _per_run_data *previousPerRun = __CFRunLoopPushPerRunData(rl);
CFRunLoopModeRef previousMode = rl->_currentMode;
rl->_currentMode = currentMode;
int32_t result;
result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode);
if (currentMode->_observerMask & kCFRunLoopExit ) __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit);
__CFRunLoopModeUnlock(currentMode);
- if (rl->_stopped) CFAllocatorDeallocate(kCFAllocatorSystemDefault, (uint32_t *)rl->_stopped);
- rl->_stopped = previousStopped;
+ __CFRunLoopPopPerRunData(rl, previousPerRun);
rl->_currentMode = previousMode;
__CFRunLoopUnlock(rl);
return result;
CHECK_FOR_FORK();
// This lock is crucial to ignorable wakeups, do not remove it.
__CFRunLoopLock(rl);
- if (rl->_ignoreWakeUps) {
+ if (__CFRunLoopIsIgnoringWakeUps(rl)) {
__CFRunLoopUnlock(rl);
return;
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
kern_return_t ret;
/* We unconditionally try to send the message, since we don't want
* 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;
}
-#else
+#elif DEPLOYMENT_TARGET_WINDOWS
SetEvent(rl->_wakeUpPort);
#endif
__CFRunLoopUnlock(rl);
} else {
mode = NULL;
}
-#if DEPLOYMENT_TARGET_WINDOWS
- // <rdar://problem/7659483> clang ObjC rewriter: __typeof(block) not rewritten correctly
- block = (void (^)(void))_Block_copy(block);
-#else
block = Block_copy(block);
-#endif
if (!mode || !block) {
if (mode) CFRelease(mode);
if (block) Block_release(block);
return hasValue;
}
-void CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef modeName) {
+void CFRunLoopAddTimer(CFRunLoopRef rl, CFRunLoopTimerRef rlt, CFStringRef modeName) {
CHECK_FOR_FORK();
if (__CFRunLoopIsDeallocating(rl)) return;
if (!__CFIsValid(rlt) || (NULL != rlt->_runLoop && rlt->_runLoop != rl)) return;
__CFRunLoopTimerUnlock(rlt);
CFArrayRemoveValueAtIndex(rlm->_timers, idx);
if (0 == CFArrayGetCount(rlm->_timers)) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
AbsoluteTime dummy;
mk_timer_cancel(rlm->_timerPort, &dummy);
-#elif DEPLOYMENT_TARGET_WINDOWS
- CancelWaitableTimer(rlm->_timerPort);
-#endif
} else if (0 == idx) {
- 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;
- }
- }
- if (nextTimer) {
- int64_t fireTSR = nextTimer->_fireTSR;
- fireTSR = (fireTSR / tenus + 1) * tenus;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
- mk_timer_arm(rlm->_timerPort, __CFUInt64ToAbsoluteTime(fireTSR));
-#elif DEPLOYMENT_TARGET_WINDOWS
- LARGE_INTEGER dueTime;
- dueTime.QuadPart = __CFTSRToFiletime(fireTSR);
- SetWaitableTimer(rlm->_timerPort, &dueTime, 0, NULL, NULL, FALSE);
-#endif
- }
+ __CFArmNextTimerInMode(rlm);
}
}
if (NULL != rlm) {
void *addr = rls->_context.version0.version == 0 ? (void *)rls->_context.version0.perform : (rls->_context.version0.version == 1 ? (void *)rls->_context.version1.perform : NULL);
#if DEPLOYMENT_TARGET_WINDOWS
contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopSource context>{version = %ld, info = %p, callout = %p}"), rls->_context.version0.version, rls->_context.version0.info, addr);
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
Dl_info info;
const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopSource context>{version = %ld, info = %p, callout = %s (%p)}"), rls->_context.version0.version, rls->_context.version0.info, name, addr);
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
}
#if DEPLOYMENT_TARGET_WINDOWS
CHECK_FOR_FORK();
CFRunLoopSourceRef memory;
uint32_t size;
- if (NULL == context) HALT;
+ if (NULL == context) {
+ CRSetCrashLogMessage("*** NULL context value passed to CFRunLoopSourceCreate(). ***");
+ HALT;
+ }
size = sizeof(struct __CFRunLoopSource) - sizeof(CFRuntimeBase);
memory = (CFRunLoopSourceRef)_CFRuntimeCreateInstance(allocator, __kCFRunLoopSourceTypeID, size, NULL);
if (NULL == memory) {
}
#if DEPLOYMENT_TARGET_WINDOWS
result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopObserver %p [%p]>{valid = %s, activities = 0x%x, repeats = %s, order = %d, callout = %p, context = %@}"), cf, CFGetAllocator(rlo), __CFIsValid(rlo) ? "Yes" : "No", rlo->_activities, __CFRunLoopObserverRepeats(rlo) ? "Yes" : "No", rlo->_order, rlo->_callout, contextDesc);
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
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("<CFRunLoopObserver %p [%p]>{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);
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
CFRelease(contextDesc);
return result;
}
void *addr = (void *)rlt->_callout;
const char *name = "???";
-#if DEPLOYMENT_TARGET_WINDOWS
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#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 : "???";
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
- CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopTimer %p [%p]>{valid = %s, interval = %0.09g, next fire date = %0.09g, callout = %s (%p), context = %@}"), cf, CFGetAllocator(rlt), __CFIsValid(rlt) ? "Yes" : "No", rlt->_interval, rlt->_nextFireDate, name, addr, contextDesc);
+ CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopTimer %p [%p]>{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);
CFRelease(contextDesc);
return result;
}
CFAbsoluteTime CFRunLoopTimerGetNextFireDate(CFRunLoopTimerRef rlt) {
CHECK_FOR_FORK();
- CF_OBJC_FUNCDISPATCH0(__kCFRunLoopTimerTypeID, CFAbsoluteTime, rlt, "_cffireTime");
+ CF_OBJC_FUNCDISPATCHV(__kCFRunLoopTimerTypeID, CFAbsoluteTime, (NSTimer *)rlt, _cffireTime);
__CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID);
CFAbsoluteTime at = 0.0;
__CFRunLoopTimerLock(rlt);
CFTimeInterval CFRunLoopTimerGetInterval(CFRunLoopTimerRef rlt) {
CHECK_FOR_FORK();
- CF_OBJC_FUNCDISPATCH0(__kCFRunLoopTimerTypeID, CFTimeInterval, rlt, "timeInterval");
+ CF_OBJC_FUNCDISPATCHV(__kCFRunLoopTimerTypeID, CFTimeInterval, (NSTimer *)rlt, timeInterval);
__CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID);
return rlt->_interval;
}
void CFRunLoopTimerInvalidate(CFRunLoopTimerRef rlt) { /* DOES CALLOUT */
CHECK_FOR_FORK();
- CF_OBJC_FUNCDISPATCH0(__kCFRunLoopTimerTypeID, void, rlt, "invalidate");
+ CF_OBJC_FUNCDISPATCHV(__kCFRunLoopTimerTypeID, void, (NSTimer *)rlt, invalidate);
__CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID);
__CFRunLoopTimerLock(rlt);
if (!__CFRunLoopTimerIsDeallocating(rlt)) {
Boolean CFRunLoopTimerIsValid(CFRunLoopTimerRef rlt) {
CHECK_FOR_FORK();
- CF_OBJC_FUNCDISPATCH0(__kCFRunLoopTimerTypeID, Boolean, rlt, "isValid");
+ CF_OBJC_FUNCDISPATCHV(__kCFRunLoopTimerTypeID, Boolean, (NSTimer *)rlt, isValid);
__CFGenericValidateType(rlt, __kCFRunLoopTimerTypeID);
return __CFIsValid(rlt);
}
*/
/* CFRunLoop.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFRUNLOOP__)
};
/* Run Loop Observer Activities */
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0),
kCFRunLoopBeforeTimers = (1UL << 1),
kCFRunLoopBeforeSources = (1UL << 2),
kCFRunLoopExit = (1UL << 7),
kCFRunLoopAllActivities = 0x0FFFFFFFU
};
-typedef CFOptionFlags CFRunLoopActivity;
CF_EXPORT const CFStringRef kCFRunLoopDefaultMode;
CF_EXPORT const CFStringRef kCFRunLoopCommonModes;
*/
/* CFRuntime.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#include <dlfcn.h>
#include <mach-o/dyld.h>
#include <mach/mach.h>
#include <sys/stat.h>
#include <CoreFoundation/CFStringDefaultEncoding.h>
#endif
+#if DEPLOYMENT_TARGET_EMBEDDED
+// This isn't in the embedded runtime.h header
+OBJC_EXPORT void *objc_destructInstance(id obj);
+#endif
#define FAKE_INSTRUMENTS 0
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+__private_extern__ void __CFOAInitializeNSObject(void); // from NSObject.m
bool __CFOASafe = false;
void (*__CFObjectAllocSetLastAllocEventNameFunction)(void *, const char *) = NULL;
void __CFOAInitialize(void) {
- static void (*dyfunc)(void) = (void *)~0;
- if (NULL == __CFgetenv("OAKeepAllocationStatistics")) return;
- if ((void *)~0 == dyfunc) {
- dyfunc = dlsym(RTLD_DEFAULT, "_OAInitialize");
- }
- if (NULL != dyfunc) {
- dyfunc();
- __CFObjectAllocRecordAllocationFunction = dlsym(RTLD_DEFAULT, "_OARecordAllocationEvent");
- __CFObjectAllocSetLastAllocEventNameFunction = dlsym(RTLD_DEFAULT, "_OASetLastAllocationEventName");
- __CFOASafe = true;
- }
}
void __CFRecordAllocationEvent(int eventnum, void *ptr, int64_t size, uint64_t data, const char *classname) {
// the lock does not protect most reading of these; we just leak the old table to allow read-only accesses to continue to work
static CFSpinLock_t __CFBigRuntimeFunnel = CFSpinLockInit;
-static CFRuntimeClass * __CFRuntimeClassTable[__CFRuntimeClassTableSize] = {0};
-static int32_t __CFRuntimeClassTableCount = 0;
+__private_extern__ CFRuntimeClass * __CFRuntimeClassTable[__CFRuntimeClassTableSize] = {0};
+__private_extern__ int32_t __CFRuntimeClassTableCount = 0;
__private_extern__ uintptr_t __CFRuntimeObjCClassTable[__CFRuntimeClassTableSize] = {0};
bool (*__CFObjCIsCollectable)(void *) = NULL;
#endif
+#if !__CONSTANT_CFSTRINGS__ || DEPLOYMENT_TARGET_EMBEDDED_MINI
// Compiler uses this symbol name; must match compiler built-in decl, so we use 'int'
#if __LP64__
int __CFConstantStringClassReference[24] = {0};
#else
int __CFConstantStringClassReference[12] = {0};
#endif
-void *__CFConstantStringClassReferencePtr = &__CFConstantStringClassReference;
+#endif
+
+#if __LP64__
+int __CFConstantStringClassReference[24] = {0};
+#else
+int __CFConstantStringClassReference[12] = {0};
+#endif
+
+void *__CFConstantStringClassReferencePtr = NULL;
Boolean _CFIsObjC(CFTypeID typeID, void *obj) {
return CF_IS_OBJC(typeID, obj);
__private_extern__ uint8_t __CFZombieEnabled = 0;
__private_extern__ uint8_t __CFDeallocateZombies = 0;
+extern void __CFZombifyNSObject(void); // from NSObject.m
+
void _CFEnableZombies(void) {
- __CFZombieEnabled = 0xFF;
}
#endif /* DEBUG */
#if DEPLOYMENT_TARGET_MACOSX
#define NUM_EXTERN_TABLES 8
#define EXTERN_TABLE_IDX(O) (((uintptr_t)(O) >> 8) & 0x7)
-#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
+#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
#define NUM_EXTERN_TABLES 1
#define EXTERN_TABLE_IDX(O) 0
#else
CFTypeID CFGetTypeID(CFTypeRef cf) {
#if defined(DEBUG)
- if (NULL == cf) HALT;
+ if (NULL == cf) { CRSetCrashLogMessage("*** CFGetTypeID() called with NULL ***"); HALT; }
#endif
CFTYPE_OBJC_FUNCDISPATCH0(CFTypeID, cf, _cfTypeID);
__CFGenericAssertIsCF(cf);
static CFTypeRef _CFRetain(CFTypeRef cf, Boolean tryR);
CFTypeRef CFRetain(CFTypeRef cf) {
- if (NULL == cf) HALT;
+ if (NULL == cf) { CRSetCrashLogMessage("*** CFRetain() called with NULL ***"); HALT; }
if (cf) __CFGenericAssertIsCF(cf);
return _CFRetain(cf, false);
}
static void _CFRelease(CFTypeRef cf);
void CFRelease(CFTypeRef cf) {
- if (NULL == cf) HALT;
+ if (NULL == cf) { CRSetCrashLogMessage("*** CFRelease() called with NULL ***"); HALT; }
#if 0
void **addrs[2] = {&&start, &&end};
start:;
__private_extern__ void __CFAllocatorDeallocate(CFTypeRef cf);
__private_extern__ const void *__CFStringCollectionCopy(CFAllocatorRef allocator, const void *ptr) {
- if (NULL == ptr) HALT;
+ if (NULL == ptr) { CRSetCrashLogMessage("*** __CFStringCollectionCopy() called with NULL ***"); HALT; }
CFStringRef theString = (CFStringRef)ptr;
CFStringRef result = CFStringCreateCopy(_CFConvertAllocatorToGCRefZeroEquivalent(allocator), theString);
return (const void *)result;
extern void CFCollection_non_gc_storage_error(void);
__private_extern__ const void *__CFTypeCollectionRetain(CFAllocatorRef allocator, const void *ptr) {
- if (NULL == ptr) HALT;
+ 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.
if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
__private_extern__ void __CFTypeCollectionRelease(CFAllocatorRef allocator, const void *ptr) {
- if (NULL == ptr) HALT;
+ 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.
if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
#endif
static uint64_t __CFGetFullRetainCount(CFTypeRef cf) {
- if (NULL == cf) HALT;
+ if (NULL == cf) { CRSetCrashLogMessage("*** __CFGetFullRetainCount() called with NULL ***"); HALT; }
#if __LP64__
uint32_t lowBits = ((CFRuntimeBase *)cf)->_rc;
if (0 == lowBits) {
}
CFIndex CFGetRetainCount(CFTypeRef cf) {
- if (NULL == cf) HALT;
+ if (NULL == cf) { CRSetCrashLogMessage("*** CFGetRetainCount() called with NULL ***"); HALT; }
uint32_t cfinfo = *(uint32_t *)&(((CFRuntimeBase *)cf)->_cfinfo);
if (cfinfo & 0x800000) { // custom ref counting for object
CFTypeID typeID = (cfinfo >> 8) & 0x03FF; // mask up to 0x0FFF
}
Boolean CFEqual(CFTypeRef cf1, CFTypeRef cf2) {
- if (NULL == cf1) HALT;
- if (NULL == cf2) HALT;
+ if (NULL == cf1) { CRSetCrashLogMessage("*** CFEqual() called with NULL first argument ***"); HALT; }
+ if (NULL == cf2) { CRSetCrashLogMessage("*** CFEqual() called with NULL second argument ***"); HALT; }
if (cf1 == cf2) return true;
CFTYPE_OBJC_FUNCDISPATCH1(Boolean, cf1, isEqual:, cf2);
CFTYPE_OBJC_FUNCDISPATCH1(Boolean, cf2, isEqual:, cf1);
}
CFHashCode CFHash(CFTypeRef cf) {
- if (NULL == cf) HALT;
+ if (NULL == cf) { CRSetCrashLogMessage("*** CFHash() called with NULL ***"); HALT; }
CFTYPE_OBJC_FUNCDISPATCH0(CFHashCode, cf, hash);
__CFGenericAssertIsCF(cf);
CFHashCode (*hash)(CFTypeRef cf) = __CFRuntimeClassTable[__CFGenericTypeID_inline(cf)]->hash;
extern void __CFErrorInitialize(void);
extern void __CFTreeInitialize(void);
extern void __CFURLInitialize(void);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
extern void __CFMachPortInitialize(void);
#endif
extern void __CFMessagePortInitialize(void);
extern void __CFRunLoopObserverInitialize(void);
extern void __CFRunLoopSourceInitialize(void);
extern void __CFRunLoopTimerInitialize(void);
+extern void __CFPFactoryInitialize(void);
extern void __CFBundleInitialize(void);
extern void __CFPlugInInitialize(void);
extern void __CFPlugInInstanceInitialize(void);
extern void __CFCalendarInitialize();
extern void __CFTimeZoneInitialize();
#endif
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+extern void __CFXPreferencesInitialize(void);
+#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#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;
+__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
asm(".desc ___crashreporter_info__, 0x10");
static void __01121__(void) {
// This is not a problem for CF.
if (__CF120290) {
__CF120293 = true;
+#if DEPLOYMENT_TARGET_MACOSX
if (__CF120291) {
- __crashreporter_info__ = "*** multi-threaded process forked ***";
+ CRSetCrashLogMessage2("*** multi-threaded process forked ***");
} else {
- __crashreporter_info__ = "*** single-threaded process forked ***";
+ CRSetCrashLogMessage2("*** single-threaded process forked ***");
}
+#endif
}
}
const void *__CFArgStuff = NULL;
__private_extern__ void *__CFAppleLanguages = NULL;
+// do not cache CFFIXED_USER_HOME or HOME, there are situations where they can change
+
static struct {
const char *name;
const char *value;
} __CFEnv[] = {
{"PATH", NULL},
- {"HOME", NULL},
{"USER", NULL},
{"HOMEPATH", NULL},
{"HOMEDRIVE", NULL},
{"NEXT_ROOT", NULL},
{"DYLD_IMAGE_SUFFIX", NULL},
{"CFProcessPath", NULL},
- {"CFFIXED_USER_HOME", NULL},
{"CFNETWORK_LIBRARY_PATH", NULL},
{"CFUUIDVersionNumber", NULL},
{"CFDebugNamedDataSharing", NULL},
{"CF_CHARSET_PATH", NULL},
{"__CF_USER_TEXT_ENCODING", NULL},
{"__CFPREFERENCES_AUTOSYNC_INTERVAL", NULL},
- {"__CFPREFERENCES_USE_OLD_UID_BEHAVIOR", NULL},
+ {"__CFPREFERENCES_LOG_FAILURES", NULL},
{"CFNumberDisableCache", NULL},
+ {"__CFPREFERENCES_AVOID_DAEMON", NULL},
{NULL, NULL}, // the last one is for optional "COMMAND_MODE" "legacy", do not use this slot, insert before
};
if (!__CFInitialized && !__CFInitializing) {
__CFInitializing = 1;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+#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
#endif
__CFProphylacticAutofsAccess = true;
- for (CFIndex idx = 0; idx < sizeof(__CFEnv) / sizeof(__CFEnv[0]); idx++) {
- __CFEnv[idx].value = __CFEnv[idx].name ? getenv(__CFEnv[idx].name) : NULL;
- }
-
+ for (CFIndex idx = 0; idx < sizeof(__CFEnv) / sizeof(__CFEnv[0]); idx++) {
+ __CFEnv[idx].value = __CFEnv[idx].name ? getenv(__CFEnv[idx].name) : NULL;
+ }
+
#if !defined(kCFUseCollectableAllocator)
kCFUseCollectableAllocator = objc_collectingEnabled();
#endif
__CFObjCIsCollectable = (bool (*)(void *))objc_isAuto;
#endif
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
UInt32 s, r;
__CFStringGetUserDefaultEncoding(&s, &r); // force the potential setenv to occur early
pthread_atfork(__01121__, NULL, __01123__);
#endif
-#if defined(DEBUG) || defined(ENABLE_ZOMBIES)
- const char *value = __CFgetenv("NSZombieEnabled");
- if (value && (*value == 'Y' || *value == 'y')) __CFZombieEnabled = 0xff;
- value = __CFgetenv("NSDeallocateZombies");
- if (value && (*value == 'Y' || *value == 'y')) __CFDeallocateZombies = 0xff;
-
-#endif
memset(__CFRuntimeClassTable, 0, sizeof(__CFRuntimeClassTable));
memset(__CFRuntimeObjCClassTable, 0, sizeof(__CFRuntimeObjCClassTable));
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
__CFBundleInitialize();
+ __CFPFactoryInitialize();
#endif
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
__CFPlugInInitialize();
__CFPlugInInstanceInitialize();
#endif
__CFUUIDInitialize();
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS
__CFMessagePortInitialize();
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
__CFMachPortInitialize();
#endif
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
__CFStreamInitialize();
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_WINDOWS
+ __CFWindowsNamedPipeInitialize();
+#endif
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS
__CFRunLoopInitialize();
__CFRunLoopObserverInitialize();
__CFRunLoopSourceInitialize();
__CFRunLoopTimerInitialize();
#endif
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
__CFTimeZoneInitialize();
__CFCalendarInitialize();
#if DEPLOYMENT_TARGET_LINUX
__CFTimeZoneInitialize();
__CFCalendarInitialize();
#endif
-
+#endif
{
CFIndex idx, cnt;
char **args;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
args = *_NSGetArgv();
cnt = *_NSGetArgc();
#elif DEPLOYMENT_TARGET_WINDOWS
_CFProcessPath(); // cache this early
-
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
__CFOAInitialize();
-#endif
+
if (__CFRuntimeClassTableCount < 256) __CFRuntimeClassTableCount = 256;
+#if defined(DEBUG) || defined(ENABLE_ZOMBIES)
+ const char *value = __CFgetenv("NSZombieEnabled");
+ if (value && (*value == 'Y' || *value == 'y')) _CFEnableZombies();
+ value = __CFgetenv("NSDeallocateZombies");
+ if (value && (*value == 'Y' || *value == 'y')) __CFDeallocateZombies = 0xff;
+#endif
+
#if defined(DEBUG) && (DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
CFLog(kCFLogLevelWarning, CFSTR("Assertions enabled"));
#endif
#if DEPLOYMENT_TARGET_WINDOWS
+__private_extern__ void __CFStringCleanup(void);
+__private_extern__ void __CFSocketCleanup(void);
+__private_extern__ void __CFUniCharCleanup(void);
+__private_extern__ void __CFStreamCleanup(void);
+
static CFBundleRef RegisterCoreFoundationBundle(void) {
#ifdef _DEBUG
// might be nice to get this from the project file at some point
#define RC_DEALLOCATING_BIT (0x400000ULL)
#endif
-#if COCOA_ARR1 && __LP64__
+#if !DEPLOYMENT_TARGET_WINDOWS && __LP64__
static bool (*CAS64)(int64_t, int64_t, volatile int64_t *) = OSAtomicCompareAndSwap64Barrier;
#else
static bool (*CAS32)(int32_t, int32_t, volatile int32_t *) = OSAtomicCompareAndSwap32Barrier;
Boolean didAuto = false;
#if __LP64__
if (0 == ((CFRuntimeBase *)cf)->_rc && !CF_IS_COLLECTABLE(cf)) return cf; // Constant CFTypeRef
-#if COCOA_ARR1
+#if !DEPLOYMENT_TARGET_WINDOWS
uint64_t allBits;
do {
allBits = *(uint64_t *)&(((CFRuntimeBase *)cf)->_cfinfo);
bool success = 0;
do {
cfinfo = *infoLocation;
-#if COCOA_ARR1
+#if !DEPLOYMENT_TARGET_WINDOWS
// if already deallocating, don't allow new retain
if (tryR && (cfinfo & 0x400000)) return NULL;
#endif
// 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
return _CFRetain(cf, true);
}
Boolean _CFIsDeallocating(CFTypeRef cf) {
if (NULL == cf) return false;
+ if (CF_IS_TAGGED_OBJ(cf)) return false;
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
return;
}
+ CFIndex start_rc = __builtin_expect(__CFOASafe, 0) ? CFGetRetainCount(cf) : 0;
Boolean isAllocator = (__kCFAllocatorTypeID_CONST == typeID);
Boolean didAuto = false;
#if __LP64__
-#if COCOA_ARR1
+#if !DEPLOYMENT_TARGET_WINDOWS
uint32_t lowBits;
uint64_t allBits;
again:;
}
#endif
#else
-#if COCOA_ARR1
+#if !DEPLOYMENT_TARGET_WINDOWS
again:;
volatile uint32_t *infoLocation = (uint32_t *)&(((CFRuntimeBase *)cf)->_cfinfo);
CFIndex rcLowBits = __CFBitfieldGetValue(cfinfo, RC_END, RC_START);
#endif
#endif
if (!didAuto && __builtin_expect(__CFOASafe, 0)) {
- __CFRecordAllocationEvent(__kCFReleaseEvent, (void *)cf, 0, CFGetRetainCount(cf), NULL);
+ __CFRecordAllocationEvent(__kCFReleaseEvent, (void *)cf, 0, start_rc - 1, NULL);
}
return;
*/
/* CFRuntime.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFRUNTIME__)
*/
/* CFSet.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
Machine generated from Notes/HashingCode.template
*/
#include "CFBasicHash.h"
#include <CoreFoundation/CFString.h>
+
#define CFDictionary 0
#define CFSet 0
#define CFBag 0
} else {
newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0);
}
- if (!newcb) HALT;
+ if (!newcb) return NULL;
memmove(newcb, (void *)cb, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *));
return newcb;
}
} else {
newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0);
}
- if (!newcb) HALT;
+ if (!newcb) return NULL;
newcb->copyCallbacks = __CFSetCopyCallbacks;
newcb->freeCallbacks = __CFSetFreeCallbacks;
newcb->retainValue = __CFSetRetainValue;
}
CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb);
- CFBasicHashSetSpecialBits(ht, specialBits);
+ if (ht) CFBasicHashSetSpecialBits(ht, specialBits);
+ if (!ht && !CF_IS_COLLECTABLE_ALLOCATOR(allocator)) CFAllocatorDeallocate(allocator, cb);
return ht;
}
CFTypeID typeID = CFSetGetTypeID();
CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
CFBasicHashRef ht = __CFSetCreateGeneric(allocator, keyCallBacks, valueCallBacks, CFDictionary);
+ if (!ht) return NULL;
if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
for (CFIndex idx = 0; idx < numValues; idx++) {
CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
CFTypeID typeID = CFSetGetTypeID();
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);
if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (mutable)");
CFDictionaryGetKeysAndValues(other, klist, vlist);
#endif
ht = __CFSetCreateGeneric(allocator, & kCFTypeSetKeyCallBacks, CFDictionary ? & kCFTypeSetValueCallBacks : NULL, CFDictionary);
- if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
- for (CFIndex idx = 0; idx < numValues; idx++) {
+ if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+ for (CFIndex idx = 0; ht && idx < numValues; idx++) {
CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
}
if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
} else {
ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
}
+ if (!ht) return NULL;
CFBasicHashMakeImmutable(ht);
*(uintptr_t *)ht = __CFISAForTypeID(typeID);
_CFRuntimeSetInstanceTypeID(ht, typeID);
CFDictionaryGetKeysAndValues(other, klist, vlist);
#endif
ht = __CFSetCreateGeneric(allocator, & kCFTypeSetKeyCallBacks, CFDictionary ? & kCFTypeSetValueCallBacks : NULL, CFDictionary);
- if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
- for (CFIndex idx = 0; idx < numValues; idx++) {
+ if (ht && 0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+ for (CFIndex idx = 0; ht && idx < numValues; idx++) {
CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
}
if (klist != kbuffer && klist != vlist) CFAllocatorDeallocate(kCFAllocatorSystemDefault, klist);
} else {
ht = CFBasicHashCreateCopy(allocator, (CFBasicHashRef)other);
}
+ if (!ht) return NULL;
*(uintptr_t *)ht = __CFISAForTypeID(typeID);
_CFRuntimeSetInstanceTypeID(ht, typeID);
if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFSet (mutable)");
}
CFIndex CFSetGetCount(CFHashRef hc) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFSetTypeID, CFIndex, hc, "count");
- if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFSetTypeID, CFIndex, hc, "count");
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSDictionary *)hc, count);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSSet *)hc, count);
__CFGenericValidateType(hc, __kCFSetTypeID);
return CFBasicHashGetCount((CFBasicHashRef)hc);
}
#if CFSet || CFBag
CFIndex CFSetGetCountOfValue(CFHashRef hc, const_any_pointer_t key) {
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, CFIndex, hc, "countForKey:", key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, CFIndex, hc, "countForObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSDictionary *)hc, countForKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSSet *)hc, countForObject:(id)key);
__CFGenericValidateType(hc, __kCFSetTypeID);
return CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key);
}
#if CFSet || CFBag
Boolean CFSetContainsValue(CFHashRef hc, const_any_pointer_t key) {
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, char, hc, "containsKey:", key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, char, hc, "containsObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, char, (NSDictionary *)hc, containsKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, char, (NSSet *)hc, containsObject:(id)key);
__CFGenericValidateType(hc, __kCFSetTypeID);
return (0 < CFBasicHashGetCountOfKey((CFBasicHashRef)hc, (uintptr_t)key));
}
const_any_pointer_t CFSetGetValue(CFHashRef hc, const_any_pointer_t key) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, const_any_pointer_t, hc, "objectForKey:", key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, const_any_pointer_t, hc, "member:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, const_any_pointer_t, (NSDictionary *)hc, objectForKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, const_any_pointer_t, (NSSet *)hc, member:(id)key);
__CFGenericValidateType(hc, __kCFSetTypeID);
CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
return (0 < bkt.count ? (const_any_pointer_t)bkt.weak_value : 0);
}
Boolean CFSetGetValueIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *value) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, Boolean, hc, "__getValue:forKey:", (any_t *)value, key);
- if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, Boolean, hc, "__getValue:forObj:", (any_t *)value, key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, Boolean, (NSDictionary *)hc, __getValue:(id *)value forKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, Boolean, (NSSet *)hc, __getValue:(id *)value forObj:(id)key);
__CFGenericValidateType(hc, __kCFSetTypeID);
CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
if (0 < bkt.count) {
#if CFDictionary
CFIndex CFDictionaryGetCountOfValue(CFHashRef hc, const_any_pointer_t value) {
- CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, CFIndex, hc, "countForObject:", value);
+ CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, CFIndex, (NSDictionary *)hc, countForObject:(id)value);
__CFGenericValidateType(hc, __kCFSetTypeID);
return CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value);
}
Boolean CFDictionaryContainsValue(CFHashRef hc, const_any_pointer_t value) {
- CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, char, hc, "containsObject:", value);
+ CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, char, (NSDictionary *)hc, containsObject:(id)value);
__CFGenericValidateType(hc, __kCFSetTypeID);
return (0 < CFBasicHashGetCountOfValue((CFBasicHashRef)hc, (uintptr_t)value));
}
CF_EXPORT Boolean CFDictionaryGetKeyIfPresent(CFHashRef hc, const_any_pointer_t key, const_any_pointer_t *actualkey) {
- CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, Boolean, hc, "getActualKey:forKey:", actualkey, key);
__CFGenericValidateType(hc, __kCFSetTypeID);
CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
if (0 < bkt.count) {
void CFSetGetValues(CFHashRef hc, const_any_pointer_t *keybuf) {
const_any_pointer_t *valuebuf = 0;
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, void, hc, "getObjects:andKeys:", (any_t *)valuebuf, (any_t *)keybuf);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, void, hc, "getObjects:", (any_t *)keybuf);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSDictionary *)hc, getObjects:(id *)valuebuf andKeys:(id *)keybuf);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSSet *)hc, getObjects:(id *)keybuf);
__CFGenericValidateType(hc, __kCFSetTypeID);
if (kCFUseCollectableAllocator) {
CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc);
void CFSetApplyFunction(CFHashRef hc, CFSetApplierFunction applier, any_pointer_t context) {
FAULT_CALLBACK((void **)&(applier));
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, void, hc, "__apply:context:", applier, context);
- if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, void, hc, "__applyValues:context:", applier, context);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSDictionary *)hc, __apply:(void (*)(const void *, const void *, void *))applier context:(void *)context);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSSet *)hc, __applyValues:(void (*)(const void *, void *))applier context:(void *)context);
__CFGenericValidateType(hc, __kCFSetTypeID);
CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
#if CFDictionary
void CFSetAddValue(CFMutableHashRef hc, const_any_pointer_t key) {
const_any_pointer_t value = key;
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, void, hc, "addObject:forKey:", value, key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, void, hc, "addObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, __addObject:(id)value forKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, addObject:(id)key);
__CFGenericValidateType(hc, __kCFSetTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
void CFSetReplaceValue(CFMutableHashRef hc, const_any_pointer_t key) {
const_any_pointer_t value = key;
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, void, hc, "replaceObject:forKey:", value, key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, void, hc, "replaceObject:", key);
+ 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);
__CFGenericValidateType(hc, __kCFSetTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
void CFSetSetValue(CFMutableHashRef hc, const_any_pointer_t key) {
const_any_pointer_t value = key;
#endif
- if (CFDictionary) CF_OBJC_FUNCDISPATCH2(__kCFSetTypeID, void, hc, "setObject:forKey:", value, key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, void, hc, "setObject:", 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);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
}
void CFSetRemoveValue(CFMutableHashRef hc, const_any_pointer_t key) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, void, hc, "removeObjectForKey:", key);
- if (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFSetTypeID, void, hc, "removeObject:", key);
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, removeObjectForKey:(id)key);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, removeObject:(id)key);
__CFGenericValidateType(hc, __kCFSetTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
}
void CFSetRemoveAllValues(CFMutableHashRef hc) {
- if (CFDictionary) CF_OBJC_FUNCDISPATCH0(__kCFSetTypeID, void, hc, "removeAllObjects");
- if (CFSet) CF_OBJC_FUNCDISPATCH0(__kCFSetTypeID, void, hc, "removeAllObjects");
+ if (CFDictionary) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableDictionary *)hc, removeAllObjects);
+ if (CFSet) CF_OBJC_FUNCDISPATCHV(__kCFSetTypeID, void, (NSMutableSet *)hc, removeAllObjects);
__CFGenericValidateType(hc, __kCFSetTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {
*/
/* CFSet.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
/*!
@header CFSet
#include <CoreFoundation/CFBase.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
/*!
void CFSetRemoveAllValues(CFMutableSetRef theSet);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFSET__ */
*/
/* CFSocket.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
#include <CoreFoundation/CFSocket.h>
#include "CFInternal.h"
#include <dispatch/dispatch.h>
+#include <dispatch/private.h>
#include <netinet/in.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <math.h>
#include <limits.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#include <sys/sysctl.h>
#include <sys/un.h>
#include <libc.h>
typedef int32_t fd_mask;
typedef int socklen_t;
-// not entirely correct, but good enough for what it's used for here
-void gettimeofday(struct timeval *tp, void *tzp) {
- tp->tv_sec = 0;
- tp->tv_usec = 0;
-}
+#define gettimeofday _NS_gettimeofday
+__private_extern__ 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) \
//#define LOG_CFSOCKET
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#define INVALID_SOCKET (CFSocketNativeHandle)(-1)
#define closesocket(a) close((a))
#define ioctlsocket(a,b,c) ioctl((a),(b),(c))
}
static SInt32 __CFSocketCreateWakeupSocketPair(void) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
SInt32 error;
error = socketpair(PF_LOCAL, SOCK_DGRAM, 0, __CFWakeupSocketPair);
result = CFStringCreateMutable(CFGetAllocator(s), 0);
__CFSocketLock(s);
void *addr = s->_callout;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
Dl_info info;
const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
#else
CFTypeID CFSocketGetTypeID(void) {
if (_kCFRuntimeNotATypeID == __kCFSocketTypeID) {
__kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
struct rlimit lim1;
int ret1 = getrlimit(RLIMIT_NOFILE, &lim1);
int mib[] = {CTL_KERN, KERN_MAXFILESPERPROC};
s->_addressQueue = NULL;
}
s->_socketSetCount = 0;
- for (idx = CFArrayGetCount(s->_runLoops); idx--;) {
- CFRunLoopWakeUp((CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx));
- }
+
+ // we'll need this later
+ CFArrayRef runLoops = (CFArrayRef)CFRetain(s->_runLoops);
CFRelease(s->_runLoops);
+
s->_runLoops = NULL;
source0 = s->_source0;
s->_source0 = NULL;
s->_context.release = 0;
s->_context.copyDescription = 0;
__CFSocketUnlock(s);
+
+ // Do this after the socket unlock to avoid deadlock (10462525)
+ for (idx = CFArrayGetCount(runLoops); idx--;) {
+ CFRunLoopWakeUp((CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, idx));
+ }
+ CFRelease(runLoops);
+
if (NULL != contextRelease) {
contextRelease(contextInfo);
}
if (!name || namelen <= 0) return kCFSocketError;
CFSocketNativeHandle sock = CFSocketGetNative(s);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
// Verify that the namelen is correct. If not, we have to fix it up. Developers will often incorrectly use 0 or strlen(path). See 9217961 and the second half of 9098274.
// Max size is a size byte, plus family byte, plus path of 255, plus a null byte.
char newName[255];
if (!name || namelen <= 0) return kCFSocketError;
CFSocketNativeHandle sock = CFSocketGetNative(s);
{
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
SInt32 flags = fcntl(sock, F_GETFL, 0);
if (flags >= 0) wasBlocking = ((flags & O_NONBLOCK) == 0);
if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(sock, FIONBIO, (u_long *)&yes);
if (0 >= protocol && SOCK_STREAM == socketType) protocol = IPPROTO_TCP;
if (0 >= protocol && SOCK_DGRAM == socketType) protocol = IPPROTO_UDP;
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
if (PF_LOCAL == protocolFamily && 0 >= socketType) socketType = SOCK_STREAM;
#endif
#if DEPLOYMENT_TARGET_WINDOWS
static void __CFSocketValidateSignature(const CFSocketSignature *providedSignature, CFSocketSignature *signature, uint16_t defaultPortNumber) {
struct sockaddr_in sain, *sainp;
memset(&sain, 0, sizeof(sain));
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
sain.sin_len = sizeof(sain);
#endif
sain.sin_family = AF_INET;
} else {
sainp = (struct sockaddr_in *)CFDataGetBytePtr(providedSignature->address);
if ((int)sizeof(struct sockaddr_in) <= CFDataGetLength(providedSignature->address) && (AF_INET == sainp->sin_family || 0 == sainp->sin_family)) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
sain.sin_len = sizeof(sain);
#endif
sain.sin_family = AF_INET;
*/
/* CFSocket.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFSOCKET__)
*/
/* Values for CFSocketError */
-enum {
+typedef CF_ENUM(CFIndex, CFSocketError) {
kCFSocketSuccess = 0,
- kCFSocketError = -1,
- kCFSocketTimeout = -2
+ kCFSocketError = -1L,
+ kCFSocketTimeout = -2L
};
-typedef CFIndex CFSocketError;
typedef struct {
SInt32 protocolFamily;
} CFSocketSignature;
/* Values for CFSocketCallBackType */
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFSocketCallBackType) {
kCFSocketNoCallBack = 0,
kCFSocketReadCallBack = 1,
kCFSocketAcceptCallBack = 2,
kCFSocketConnectCallBack = 4,
kCFSocketWriteCallBack = 8
};
-typedef CFOptionFlags CFSocketCallBackType;
/* Socket flags */
enum {
kCFSocketAutomaticallyReenableAcceptCallBack = 2,
kCFSocketAutomaticallyReenableDataCallBack = 3,
kCFSocketAutomaticallyReenableWriteCallBack = 8,
-#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
- kCFSocketLeaveErrors = 64,
-#endif
+ kCFSocketLeaveErrors CF_ENUM_AVAILABLE(10_5, 2_0) = 64,
kCFSocketCloseOnInvalidate = 128
};
CF_EXPORT CFSocketRef CFSocketCreate(CFAllocatorRef allocator, SInt32 protocolFamily, SInt32 socketType, SInt32 protocol, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context);
CF_EXPORT CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle sock, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context);
CF_EXPORT CFSocketRef CFSocketCreateWithSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context);
+/* CFSocketCreateWithSocketSignature() creates a socket of the requested type and binds its address (using CFSocketSetAddress()) to the requested address. If this fails, it returns NULL. */
CF_EXPORT CFSocketRef CFSocketCreateConnectedToSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context, CFTimeInterval timeout);
-/* CFSocketCreateWithSignature creates a socket of the requested type and binds its address (using CFSocketSetAddress) to the requested address. If this fails, it returns NULL. CFSocketCreateConnectedToSignature creates a socket suitable for connecting to the requested type and address, and connects it (using CFSocketConnectToAddress). If this fails, it returns NULL. */
+/* CFSocketCreateConnectedToSocketSignature() creates a socket suitable for connecting to the requested type and address, and connects it (using CFSocketConnectToAddress()). If this fails, it returns NULL. */
CF_EXPORT CFSocketError CFSocketSetAddress(CFSocketRef s, CFDataRef address);
CF_EXPORT CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeInterval timeout);
*/
/* CFSocketStream.c
- Copyright (c) 2000-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2000-2012, Apple Inc. All rights reserved.
Responsibility: Jeremy Wyld
*/
// Original Author: Becky Willrich
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#elif DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_WINDOWS
typedef void (*CF_SOCKET_STREAM_PAIR)(CFAllocatorRef, CFStringRef, UInt32, CFSocketNativeHandle, const CFSocketSignature*, CFReadStreamRef*, CFWriteStreamRef*);
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
// These are duplicated in CFNetwork, who actually externs them in its headers
static struct {
CFSpinLock_t lock;
UInt32 flags;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#elif DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_WINDOWS
HMODULE image;
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
void (*_CFSocketStreamCreatePair)(CFAllocatorRef, CFStringRef, UInt32, CFSocketNativeHandle, const CFSocketSignature*, CFReadStreamRef*, CFWriteStreamRef*);
CFErrorRef (*_CFErrorCreateWithStreamError)(CFAllocatorRef, CFStreamError*);
} CFNetworkSupport = {
CFSpinLockInit,
0x0,
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#elif DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_WINDOWS
NULL,
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
NULL,
NULL,
#define CFNETWORK_LOAD_SYM(sym) __CFLookupCFNetworkFunction(#sym)
#elif DEPLOYMENT_TARGET_WINDOWS
#define CFNETWORK_LOAD_SYM(sym) (void *)GetProcAddress(CFNetworkSupport.image, #sym)
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
static void initializeCFNetworkSupport(void) {
CFNetworkSupport._CFErrorCreateWithStreamError = (CFErrorRef(*)(CFAllocatorRef, CFStreamError *))CFNETWORK_LOAD_SYM(_CFErrorCreateWithStreamError);
CFNetworkSupport._CFStreamErrorFromCFError = (CFStreamError(*)(CFErrorRef))CFNETWORK_LOAD_SYM(_CFStreamErrorFromCFError);
}
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
if (!CFNetworkSupport._CFSocketStreamCreatePair) CFLog(__kCFLogAssertion, CFSTR("CoreFoundation: failed to dynamically link symbol _CFSocketStreamCreatePair"));
*/
/* CFSortFunctions.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
#include <dispatch/dispatch.h>
#endif
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#include <dispatch/private.h>
+#endif
enum {
kCFSortConcurrent = (1 << 0),
*/
/* CFStorage.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Ali Ozer
*/
}
#if 0
-#define ASSERT(x) do { if (! (x)) { fprintf(stderr, "Assertion %s failed on line %d\n", #x, __LINE__); abort(); } } while (0)
+#define ASSERT(x) do { if (! (x)) { fprintf(stderr, "Assertion %s failed on line %d\n", #x, __LINE__); HALT; } } while (0)
#else
#define ASSERT(x) do { if (0 && ! (x)) { } } while(0)
#endif
*/
/* CFStorage.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
/*!
@header CFStorage
#include <CoreFoundation/CFBase.h>
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFStorageEnumerationOptionFlags) {
kCFStorageEnumerationConcurrent = (1UL << 0) /* Allow enumeration to proceed concurrently */
};
-typedef CFOptionFlags CFStorageEnumerationOptionFlags;
CF_EXTERN_C_BEGIN
*/
/* CFStream.c
- Copyright (c) 2000-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2000-2012, Apple Inc. All rights reserved.
Responsibility: John Iarocci
*/
#include <assert.h>
#endif
+
struct CFStreamAux {
CFSpinLock_t streamLock;
CFArrayRef previousRunloopsAndModes;
CFArrayRef rlArray = _CFStreamCopyRunLoopsAndModes(stream);
if (rlArray) {
CFIndex cnt = CFArrayGetCount(rlArray);
- CFRunLoopRef rl;
+ CFRunLoopRef rl = NULL;
if (cnt == 2) {
rl = (CFRunLoopRef)CFArrayGetValueAtIndex(rlArray, 0);
}
if (NULL != rl && CFRunLoopIsWaiting(rl))
CFRunLoopWakeUp(rl);
+ CFRelease(rlArray);
}
- CFRelease(rlArray);
}
__private_extern__ void _CFStreamSignalEvent(struct _CFStream *stream, CFStreamEventType event, CFErrorRef error, Boolean synchronousAllowed) {
}
CF_EXPORT CFStreamStatus CFReadStreamGetStatus(CFReadStreamRef stream) {
- CF_OBJC_FUNCDISPATCH0(__kCFReadStreamTypeID, CFStreamStatus, stream, "streamStatus");
+ CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, CFStreamStatus, (NSInputStream *)stream, streamStatus);
return _CFStreamGetStatus((struct _CFStream *)stream);
}
CF_EXPORT CFStreamStatus CFWriteStreamGetStatus(CFWriteStreamRef stream) {
- CF_OBJC_FUNCDISPATCH0(__kCFWriteStreamTypeID, CFStreamStatus, stream, "streamStatus");
+ CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, CFStreamStatus, (NSOutputStream *)stream, streamStatus);
return _CFStreamGetStatus((struct _CFStream *)stream);
}
}
CF_EXPORT CFStreamError CFReadStreamGetError(CFReadStreamRef stream) {
- CF_OBJC_FUNCDISPATCH0(__kCFReadStreamTypeID, CFStreamError, stream, "_cfStreamError");
+ CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, CFStreamError, (NSInputStream *)stream, _cfStreamError);
return _CFStreamGetStreamError((struct _CFStream *)stream);
}
CF_EXPORT CFStreamError CFWriteStreamGetError(CFWriteStreamRef stream) {
- CF_OBJC_FUNCDISPATCH0(__kCFWriteStreamTypeID, CFStreamError, stream, "_cfStreamError");
+ CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, CFStreamError, (NSOutputStream *)stream, _cfStreamError);
return _CFStreamGetStreamError((struct _CFStream *)stream);
}
}
CF_EXPORT CFErrorRef CFReadStreamCopyError(CFReadStreamRef stream) {
- CF_OBJC_FUNCDISPATCH0(__kCFReadStreamTypeID, CFErrorRef, stream, "streamError");
+ CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, CFErrorRef, (NSInputStream *)stream, streamError);
return _CFStreamCopyError((struct _CFStream *)stream);
}
CF_EXPORT CFErrorRef CFWriteStreamCopyError(CFWriteStreamRef stream) {
return _CFStreamCopyError((struct _CFStream *)stream);
- CF_OBJC_FUNCDISPATCH0(__kCFWriteStreamTypeID, CFErrorRef, stream, "streamError");
+ CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, CFErrorRef, (NSOutputStream *)stream, streamError);
}
__private_extern__ Boolean _CFStreamOpen(struct _CFStream *stream) {
CF_EXPORT Boolean CFReadStreamOpen(CFReadStreamRef stream) {
if(CF_IS_OBJC(__kCFReadStreamTypeID, stream)) {
- CF_OBJC_VOIDCALL0(stream, "open");
+ (void)CF_OBJC_CALLV((NSInputStream *)stream, open);
return TRUE;
}
return _CFStreamOpen((struct _CFStream *)stream);
CF_EXPORT Boolean CFWriteStreamOpen(CFWriteStreamRef stream) {
if(CF_IS_OBJC(__kCFWriteStreamTypeID, stream)) {
- CF_OBJC_VOIDCALL0(stream, "open");
+ (void)CF_OBJC_CALLV((NSOutputStream *)stream, open);
return TRUE;
}
return _CFStreamOpen((struct _CFStream *)stream);
}
CF_EXPORT void CFReadStreamClose(CFReadStreamRef stream) {
- CF_OBJC_FUNCDISPATCH0(__kCFReadStreamTypeID, void, stream, "close");
+ CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, void, (NSInputStream *)stream, close);
_CFStreamClose((struct _CFStream *)stream);
}
CF_EXPORT void CFWriteStreamClose(CFWriteStreamRef stream) {
- CF_OBJC_FUNCDISPATCH0(__kCFWriteStreamTypeID, void, stream, "close");
+ CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, void, (NSOutputStream *)stream, close);
_CFStreamClose((struct _CFStream *)stream);
}
CF_EXPORT Boolean CFReadStreamHasBytesAvailable(CFReadStreamRef readStream) {
- CF_OBJC_FUNCDISPATCH0(__kCFReadStreamTypeID, Boolean, readStream, "hasBytesAvailable");
+ CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, Boolean, (NSInputStream *)readStream, hasBytesAvailable);
struct _CFStream *stream = (struct _CFStream *)readStream;
CFStreamStatus status = _CFStreamGetStatus(stream);
const struct _CFStreamCallBacks *cb;
static void waitForOpen(struct _CFStream *stream);
CFIndex CFReadStreamRead(CFReadStreamRef readStream, UInt8 *buffer, CFIndex bufferLength) {
- CF_OBJC_FUNCDISPATCH2(__kCFReadStreamTypeID, CFIndex, readStream, "read:maxLength:", buffer, bufferLength);
+ CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, CFIndex, (NSInputStream *)readStream, read:(uint8_t *)buffer maxLength:(NSUInteger)bufferLength);
struct _CFStream *stream = (struct _CFStream *)readStream;
CFStreamStatus status = _CFStreamGetStatus(stream);
const struct _CFStreamCallBacks *cb = _CFStreamGetCallBackPtr(stream);
CF_EXPORT const UInt8 *CFReadStreamGetBuffer(CFReadStreamRef readStream, CFIndex maxBytesToRead, CFIndex *numBytesRead) {
if (CF_IS_OBJC(__kCFReadStreamTypeID, readStream)) {
uint8_t *bufPtr = NULL;
- Boolean gotBytes;
- CF_OBJC_CALL2(Boolean, gotBytes, readStream, "getBuffer:length:", &bufPtr, numBytesRead);
+ Boolean gotBytes = (Boolean) CF_OBJC_CALLV((NSInputStream *)readStream, getBuffer:&bufPtr length:(NSUInteger *)numBytesRead);
if(gotBytes) {
return (const UInt8 *)bufPtr;
} else {
}
CF_EXPORT Boolean CFWriteStreamCanAcceptBytes(CFWriteStreamRef writeStream) {
- CF_OBJC_FUNCDISPATCH0(__kCFWriteStreamTypeID, Boolean, writeStream, "hasSpaceAvailable");
+ CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, Boolean, (NSOutputStream *)writeStream, hasSpaceAvailable);
struct _CFStream *stream = (struct _CFStream *)writeStream;
CFStreamStatus status = _CFStreamGetStatus(stream);
const struct _CFStreamCallBacks *cb;
}
CF_EXPORT CFIndex CFWriteStreamWrite(CFWriteStreamRef writeStream, const UInt8 *buffer, CFIndex bufferLength) {
- CF_OBJC_FUNCDISPATCH2(__kCFWriteStreamTypeID, CFIndex, writeStream, "write:maxLength:", buffer, bufferLength);
+ CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, CFIndex, (NSOutputStream *)writeStream, write:(const uint8_t *)buffer maxLength:(NSUInteger)bufferLength);
struct _CFStream *stream = (struct _CFStream *)writeStream;
CFStreamStatus status = _CFStreamGetStatus(stream);
const struct _CFStreamCallBacks *cb = _CFStreamGetCallBackPtr(stream);
}
CF_EXPORT CFTypeRef CFReadStreamCopyProperty(CFReadStreamRef stream, CFStringRef propertyName) {
- CF_OBJC_FUNCDISPATCH1(__kCFReadStreamTypeID, CFTypeRef, stream, "propertyForKey:", propertyName);
+ CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, CFTypeRef, (NSInputStream *)stream, propertyForKey:(NSString *)propertyName);
return _CFStreamCopyProperty((struct _CFStream *)stream, propertyName);
}
CF_EXPORT CFTypeRef CFWriteStreamCopyProperty(CFWriteStreamRef stream, CFStringRef propertyName) {
- CF_OBJC_FUNCDISPATCH1(__kCFWriteStreamTypeID, CFTypeRef, stream, "propertyForKey:", propertyName);
+ CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, CFTypeRef, (NSOutputStream *)stream, propertyForKey:(NSString *)propertyName);
return _CFStreamCopyProperty((struct _CFStream *)stream, propertyName);
}
CF_EXPORT
Boolean CFReadStreamSetProperty(CFReadStreamRef stream, CFStringRef propertyName, CFTypeRef propertyValue) {
- CF_OBJC_FUNCDISPATCH2(__kCFReadStreamTypeID, Boolean, stream, "setProperty:forKey:", propertyValue, propertyName);
+ CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, Boolean, (NSInputStream *)stream, setProperty:(id)propertyValue forKey:(NSString *)propertyName);
return _CFStreamSetProperty((struct _CFStream *)stream, propertyName, propertyValue);
}
CF_EXPORT
Boolean CFWriteStreamSetProperty(CFWriteStreamRef stream, CFStringRef propertyName, CFTypeRef propertyValue) {
- CF_OBJC_FUNCDISPATCH2(__kCFWriteStreamTypeID, Boolean, stream, "setProperty:forKey:", propertyValue, propertyName);
+ CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, Boolean, (NSOutputStream *)stream, setProperty:(id)propertyValue forKey:(NSString *)propertyName);
return _CFStreamSetProperty((struct _CFStream *)stream, propertyName, propertyValue);
}
}
CF_EXPORT Boolean CFReadStreamSetClient(CFReadStreamRef readStream, CFOptionFlags streamEvents, CFReadStreamClientCallBack clientCB, CFStreamClientContext *clientContext) {
- CF_OBJC_FUNCDISPATCH3(__kCFReadStreamTypeID, Boolean, readStream, "_setCFClientFlags:callback:context:", streamEvents, clientCB, clientContext);
+ CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, Boolean, (NSInputStream *)readStream, _setCFClientFlags:streamEvents callback:clientCB context:clientContext);
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_FUNCDISPATCH3(__kCFWriteStreamTypeID, Boolean, writeStream, "_setCFClientFlags:callback:context:", streamEvents, clientCB, clientContext);
+ CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, Boolean, (NSOutputStream *)writeStream, _setCFClientFlags:streamEvents callback:clientCB context:clientContext);
streamEvents &= ~kCFStreamEventHasBytesAvailable;
return _CFStreamSetClient((struct _CFStream *)writeStream, streamEvents, (void (*)(struct _CFStream *, CFStreamEventType, void *))clientCB, clientContext);
}
}
CF_EXPORT void CFReadStreamScheduleWithRunLoop(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode) {
- CF_OBJC_FUNCDISPATCH2(__kCFReadStreamTypeID, void, stream, "_scheduleInCFRunLoop:forMode:", runLoop, runLoopMode);
+ CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, void, (NSInputStream *)stream, _scheduleInCFRunLoop:runLoop forMode:runLoopMode);
_CFStreamScheduleWithRunLoop((struct _CFStream *)stream, runLoop, runLoopMode);
}
CF_EXPORT void CFWriteStreamScheduleWithRunLoop(CFWriteStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode) {
- CF_OBJC_FUNCDISPATCH2(__kCFWriteStreamTypeID, void, stream, "_scheduleInCFRunLoop:forMode:", runLoop, runLoopMode);
+ CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, void, (NSOutputStream *)stream, _scheduleInCFRunLoop:runLoop forMode:runLoopMode);
_CFStreamScheduleWithRunLoop((struct _CFStream *)stream, runLoop, runLoopMode);
}
}
CF_EXPORT void CFReadStreamUnscheduleFromRunLoop(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode) {
- CF_OBJC_FUNCDISPATCH2(__kCFReadStreamTypeID, void, stream, "_unscheduleFromCFRunLoop:forMode:", runLoop, runLoopMode);
+ CF_OBJC_FUNCDISPATCHV(__kCFReadStreamTypeID, void, (NSInputStream *)stream, _unscheduleFromCFRunLoop:runLoop forMode:runLoopMode);
_CFStreamUnscheduleFromRunLoop((struct _CFStream *)stream, runLoop, runLoopMode);
}
void CFWriteStreamUnscheduleFromRunLoop(CFWriteStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode) {
- CF_OBJC_FUNCDISPATCH2(__kCFWriteStreamTypeID, void, stream, "_unscheduleFromCFRunLoop:forMode:", runLoop, runLoopMode);
+ CF_OBJC_FUNCDISPATCHV(__kCFWriteStreamTypeID, void, (NSOutputStream *)stream, _unscheduleFromCFRunLoop:runLoop forMode:runLoopMode);
_CFStreamUnscheduleFromRunLoop((struct _CFStream *)stream, runLoop, runLoopMode);
}
return sizeof(struct _CFStream);
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#elif DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_WINDOWS
void __CFStreamCleanup(void) {
__CFSpinLock(&sSourceLock);
if (sSharedSources) {
}
__CFSpinUnlock(&sSourceLock);
}
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
*/
/* CFStream.h
- Copyright (c) 2000-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2000-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFSTREAM__)
#include <CoreFoundation/CFSocket.h>
#include <CoreFoundation/CFError.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
-enum {
+typedef CF_ENUM(CFIndex, CFStreamStatus) {
kCFStreamStatusNotOpen = 0,
kCFStreamStatusOpening, /* open is in-progress */
kCFStreamStatusOpen,
kCFStreamStatusClosed,
kCFStreamStatusError
};
-typedef CFIndex CFStreamStatus;
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFStreamEventType) {
kCFStreamEventNone = 0,
kCFStreamEventOpenCompleted = 1,
kCFStreamEventHasBytesAvailable = 2,
kCFStreamEventErrorOccurred = 8,
kCFStreamEventEndEncountered = 16
};
-typedef CFOptionFlags CFStreamEventType;
typedef struct {
CFIndex version;
CFReadStreamRef CFReadStreamCreateWithFile(CFAllocatorRef alloc, CFURLRef fileURL);
CF_EXPORT
CFWriteStreamRef CFWriteStreamCreateWithFile(CFAllocatorRef alloc, CFURLRef fileURL);
+CF_IMPLICIT_BRIDGING_DISABLED
CF_EXPORT
void CFStreamCreateBoundPair(CFAllocatorRef alloc, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream, CFIndex transferBufferSize);
+CF_IMPLICIT_BRIDGING_ENABLED
/* Property for file write streams; value should be a CFBoolean. Set to TRUE to append to a file, rather than to replace its contents */
CF_EXPORT
CF_EXPORT
const CFStringRef kCFStreamPropertySocketRemotePortNumber;
+CF_IMPLICIT_BRIDGING_DISABLED
/* Socket streams; the returned streams are paired such that they use the same socket; pass NULL if you want only the read stream or the write stream */
CF_EXPORT
void CFStreamCreatePairWithSocket(CFAllocatorRef alloc, CFSocketNativeHandle sock, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream);
void CFStreamCreatePairWithSocketToHost(CFAllocatorRef alloc, CFStringRef host, UInt32 port, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream);
CF_EXPORT
void CFStreamCreatePairWithPeerSocketSignature(CFAllocatorRef alloc, const CFSocketSignature *signature, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream);
+CF_IMPLICIT_BRIDGING_ENABLED
/* Returns the current state of the stream */
/* The following API is deprecated starting in 10.5; please use CFRead/WriteStreamCopyError(), above, instead */
-enum {
- kCFStreamErrorDomainCustom = -1, /* custom to the kind of stream in question */
+typedef CF_ENUM(CFIndex, CFStreamErrorDomain) {
+ kCFStreamErrorDomainCustom = -1L, /* custom to the kind of stream in question */
kCFStreamErrorDomainPOSIX = 1, /* POSIX errno; interpret using <sys/errno.h> */
kCFStreamErrorDomainMacOSStatus /* OSStatus type from Carbon APIs; interpret using <MacTypes.h> */
};
-typedef CFIndex CFStreamErrorDomain;
typedef struct {
CFIndex domain;
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFSTREAM__ */
*/
/* CFStreamAbstract.h
- Copyright (c) 2000-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2000-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFSTREAMABSTRACT__)
*/
/* CFStreamPriv.h
- Copyright (c) 2000-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2000-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFSTREAMPRIV__)
CF_EXTERN_C_END
+/*
+ * for CF{Read/Write}StreamCopyProperty created from a file. The
+ * result is a CFDataRef containing sizeof(int) bytes in machine byte
+ * ordering representing the file descriptor of the underlying open
+ * file. If the underlying file descriptor is not open, the property
+ * value will be NULL (as opposed to containing ((int) -1)).
+ */
+CF_EXPORT const CFStringRef _kCFStreamPropertyFileNativeHandle CF_AVAILABLE_IOS(5_0);
+
#endif /* ! __COREFOUNDATION_CFSTREAMPRIV__ */
*/
/* CFString.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, 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.
#include <CoreFoundation/CFUnicodePrecomposition.h>
#include <CoreFoundation/CFPriv.h>
#include <CoreFoundation/CFNumber.h>
+#include <CoreFoundation/CFNumberFormatter.h>
#include "CFInternal.h"
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
#include "CFLocaleInternal.h"
+#endif
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
typedef Boolean (*UNI_CHAR_FUNC)(UInt32 flags, UInt8 ch, UniChar *unicodeChar);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
extern size_t malloc_good_size(size_t size);
#endif
extern void __CFStrConvertBytesToUnicode(const uint8_t *bytes, UniChar *buffer, CFIndex numChars);
CFStringEncoding __CFDefaultEightBitStringEncoding = kCFStringEncodingInvalidId;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
#define __defaultEncoding kCFStringEncodingMacRoman
#elif DEPLOYMENT_TARGET_WINDOWS
#define __defaultEncoding kCFStringEncodingWindowsLatin1
CFStringEncoding CFStringFileSystemEncoding(void) {
if (__CFDefaultFileSystemEncoding == kCFStringEncodingInvalidId) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS
__CFDefaultFileSystemEncoding = kCFStringEncodingUTF8;
#else
__CFDefaultFileSystemEncoding = CFStringGetSystemEncoding();
*/
CF_INLINE Boolean __CFBytesInASCII(const uint8_t *bytes, CFIndex len) {
#if __LP64__
- /* Go by 8s in 64 bit */
+ /* 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;
}
if (__CFStrHasContentsAllocator(str)) { /* Also apply any preferred size from the allocator */
newCapacity = CFAllocatorGetPreferredSizeForSize(__CFStrContentsAllocator(str), newCapacity, 0);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
} else {
newCapacity = malloc_good_size(newCapacity);
#endif
CFAssert1(hasLengthAndNullBytes == __CFStrHasNullByte(str), __kCFLogAssertion, "%s(): Invalid state in 8-bit string", __PRETTY_FUNCTION__);
- if (hasLengthAndNullBytes) curContents++;
- if (useLengthAndNullBytes) newContents++;
-
+ // Calculate pointers to the actual string content (skipping over the length byte, if present). Note that keeping a reference to the base is needed for newContents under GC, since the copy may take a long time.
+ const uint8_t *curContentsBody = hasLengthAndNullBytes ? (curContents+1) : curContents;
+ uint8_t *newContentsBody = useLengthAndNullBytes ? (newContents+1) : newContents;
+
if (curContents) {
if (oldIsUnicode == newIsUnicode) {
- if (newContents == curContents) {
- rearrangeBlocks(newContents, curLength, newCharSize, deleteRanges, numDeleteRanges, insertLength);
+ if (newContentsBody == curContentsBody) {
+ rearrangeBlocks(newContentsBody, curLength, newCharSize, deleteRanges, numDeleteRanges, insertLength);
} else {
- copyBlocks(curContents, newContents, curLength, oldIsUnicode, newIsUnicode, deleteRanges, numDeleteRanges, insertLength);
+ copyBlocks(curContentsBody, newContentsBody, curLength, oldIsUnicode, newIsUnicode, deleteRanges, numDeleteRanges, insertLength);
}
} else if (newIsUnicode) { /* this implies we have a new buffer */
- copyBlocks(curContents, newContents, curLength, oldIsUnicode, newIsUnicode, deleteRanges, numDeleteRanges, insertLength);
+ copyBlocks(curContentsBody, newContentsBody, curLength, oldIsUnicode, newIsUnicode, deleteRanges, numDeleteRanges, insertLength);
}
- if (hasLengthAndNullBytes) curContents--; /* Undo the damage from above */
if (allocNewBuffer && __CFStrFreeContentsWhenDone(str)) __CFStrDeallocateMutableContents(str, (void *)curContents);
}
-
+
if (!newIsUnicode) {
if (useLengthAndNullBytes) {
- newContents[newLength] = 0; /* Always have null byte, if not unicode */
- newContents--; /* Undo the damage from above */
+ newContentsBody[newLength] = 0; /* Always have null byte, if not unicode */
newContents[0] = __CFCanUseLengthByte(newLength) ? (uint8_t)newLength : 0;
if (!hasLengthAndNullBytes) __CFStrSetHasLengthAndNullBytes(str);
} else {
if (hasLengthAndNullBytes) __CFStrClearHasLengthAndNullBytes(str);
}
__CFStrSetExplicitLength(str, newLength);
-
+
if (allocNewBuffer) {
__CFStrSetCapacity(str, newCapacity);
__CFStrClearCapacityProvidedExternally(str);
CFIndex bufLen; // Number of characters in the buffer for hashing
CFIndex len = 0; // Actual length of the string
- CF_OBJC_CALL0(CFIndex, len, str, "length");
- if (len <= HashEverythingLimit) {
- CF_OBJC_VOIDCALL2(str, "getCharacters:range:", buffer, CFRangeMake(0, len));
+ len = CF_OBJC_CALLV((NSString *)str, length);
+ if (len <= HashEverythingLimit) {
+ (void)CF_OBJC_CALLV((NSString *)str, getCharacters:buffer range:NSMakeRange(0, len));
bufLen = len;
} else {
- CF_OBJC_VOIDCALL2(str, "getCharacters:range:", buffer, CFRangeMake(0, 32));
- CF_OBJC_VOIDCALL2(str, "getCharacters:range:", buffer+32, CFRangeMake((len >> 1) - 16, 32));
- CF_OBJC_VOIDCALL2(str, "getCharacters:range:", buffer+64, CFRangeMake(len - 32, 32));
+ (void)CF_OBJC_CALLV((NSString *)str, getCharacters:buffer range:NSMakeRange(0, 32));
+ (void)CF_OBJC_CALLV((NSString *)str, getCharacters:buffer+32 range:NSMakeRange((len >> 1) - 16, 32));
+ (void)CF_OBJC_CALLV((NSString *)str, getCharacters:buffer+64 range:NSMakeRange(len - 32, 32));
bufLen = HashEverythingLimit;
}
return __CFStrHashCharacters(buffer, bufLen, len);
static Boolean CFStrIsUnicode(CFStringRef str) {
- CF_OBJC_FUNCDISPATCH0(__kCFStringTypeID, Boolean, str, "_encodingCantBeStoredInEightBitCFString");
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, Boolean, (NSString *)str, _encodingCantBeStoredInEightBitCFString);
return __CFStrIsUnicode(str);
}
// First check to see if the data needs to be converted...
// ??? We could be more efficient here and in some cases (Unicode data) eliminate a copy
- if ((encoding == kCFStringEncodingUnicode && possiblyExternalFormat) || encoding != kCFStringEncodingUnicode && ! stringSupportsEightBitCFRepresentation) {
+ if ((encoding == kCFStringEncodingUnicode && possiblyExternalFormat) || (encoding != kCFStringEncodingUnicode && ! stringSupportsEightBitCFRepresentation)) {
const void *realBytes = (uint8_t *) bytes + (hasLengthByte ? 1 : 0);
CFIndex realNumBytes = numBytes - (hasLengthByte ? 1 : 0);
Boolean usingPassedInMemory = false;
}
CFStringRef CFStringCreateWithSubstring(CFAllocatorRef alloc, CFStringRef str, CFRange range) {
-// CF_OBJC_FUNCDISPATCH1(__kCFStringTypeID, CFStringRef , str, "_createSubstringWithRange:", CFRangeMake(range.location, range.length));
+// CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, CFStringRef , (NSString *)str, _createSubstringWithRange:NSMakeRange(range.location, range.length));
__CFAssertIsString(str);
__CFAssertRangeIsInStringBounds(str, range.location, range.length);
}
CFStringRef CFStringCreateCopy(CFAllocatorRef alloc, CFStringRef str) {
-// CF_OBJC_FUNCDISPATCH0(__kCFStringTypeID, CFStringRef, str, "copy");
+// CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, CFStringRef, (NSString *)str, copy);
__CFAssertIsString(str);
if (!__CFStrIsMutable((CFStringRef)str) && // If the string is not mutable
if (__CFStrIsEightBit(result)) {
key = (char *)__CFStrContents(result) + __CFStrSkipAnyLengthByte(result);
} else { // For some reason the string is not 8-bit!
- key = (char *)CFAllocatorAllocate(kCFAllocatorSystemDefault, strlen(cStr) + 1, 0);
+ CFIndex keySize = strlen(cStr) + 1;
+ key = (char *)CFAllocatorAllocate(kCFAllocatorSystemDefault, keySize, 0);
if (__CFOASafe) __CFSetLastAllocationEventName((void *)key, "CFString (CFSTR key)");
- strlcpy(key, cStr, strlen(cStr) + 1); // !!! We will leak this, if the string is removed from the table (or table is freed)
+ strlcpy(key, cStr, keySize); // !!! We will leak this, if the string is removed from the table (or table is freed)
}
{
CFMutableStringRef CFStringCreateMutableCopy(CFAllocatorRef alloc, CFIndex maxLength, CFStringRef string) {
CFMutableStringRef newString;
- // CF_OBJC_FUNCDISPATCH0(__kCFStringTypeID, CFMutableStringRef, string, "mutableCopy");
+ // CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, CFMutableStringRef, (NSString *)string, mutableCopy);
__CFAssertIsString(string);
/* This one is for CF
*/
CFIndex CFStringGetLength(CFStringRef str) {
- CF_OBJC_FUNCDISPATCH0(__kCFStringTypeID, CFIndex, str, "length");
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, CFIndex, (NSString *)str, length);
__CFAssertIsString(str);
return __CFStrLength(str);
/* This one is for the CF API
*/
UniChar CFStringGetCharacterAtIndex(CFStringRef str, CFIndex idx) {
- CF_OBJC_FUNCDISPATCH1(__kCFStringTypeID, UniChar, str, "characterAtIndex:", idx);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, UniChar, (NSString *)str, characterAtIndex:(NSUInteger)idx);
__CFAssertIsString(str);
__CFAssertIndexIsInStringBounds(str, idx);
/* This one is for the CF API
*/
void CFStringGetCharacters(CFStringRef str, CFRange range, UniChar *buffer) {
- CF_OBJC_FUNCDISPATCH2(__kCFStringTypeID, void, str, "getCharacters:range:", buffer, range);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSString *)str, getCharacters:(unichar *)buffer range:NSMakeRange(range.location, range.length));
__CFAssertIsString(str);
__CFAssertRangeIsInStringBounds(str, range.location, range.length);
if (encoding != __CFStringGetEightBitStringEncoding() && (kCFStringEncodingASCII != __CFStringGetEightBitStringEncoding() || !__CFStringEncodingIsSupersetOfASCII(encoding))) return NULL;
// ??? Also check for encoding = SystemEncoding and perhaps bytes are all ASCII?
- CF_OBJC_FUNCDISPATCH1(__kCFStringTypeID, const char *, str, "_fastCStringContents:", true);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, const char *, (NSString *)str, _fastCStringContents:true);
__CFAssertIsString(str);
const UniChar *CFStringGetCharactersPtr(CFStringRef str) {
- CF_OBJC_FUNCDISPATCH0(__kCFStringTypeID, const UniChar *, str, "_fastCharacterContents");
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, const UniChar *, (NSString *)str, _fastCharacterContents);
__CFAssertIsString(str);
if (__CFStrIsUnicode(str)) return (const UniChar *)__CFStrContents(str);
__CFAssertIsNotNegative(bufferSize);
if (bufferSize < 1) return false;
- CF_OBJC_FUNCDISPATCH3(__kCFStringTypeID, Boolean, str, "_getCString:maxLength:encoding:", buffer, bufferSize - 1, encoding);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, Boolean, (NSString *)str, _getCString:buffer maxLength:(NSUInteger)bufferSize - 1 encoding:encoding);
__CFAssertIsString(str);
langID = "tr";
} else if (!strncmp(string, "nl", 2)) { // Dutch
langID = "nl";
+ } else if (!strncmp(string, "el", 2)) { // Greek
+ langID = "el";
}
}
CFComparisonResult CFStringCompareWithOptions(CFStringRef string, CFStringRef string2, CFRange rangeToCompare, CFStringCompareFlags compareOptions) { return CFStringCompareWithOptionsAndLocale(string, string2, rangeToCompare, compareOptions, NULL); }
-CFComparisonResult CFStringCompare(CFStringRef string, CFStringRef str2, CFOptionFlags options) {
+CFComparisonResult CFStringCompare(CFStringRef string, CFStringRef str2, CFStringCompareFlags options) {
return CFStringCompareWithOptions(string, str2, CFRangeMake(0, CFStringGetLength(string)), options);
}
}
void CFStringGetLineBounds(CFStringRef string, CFRange range, CFIndex *lineBeginIndex, CFIndex *lineEndIndex, CFIndex *contentsEndIndex) {
- CF_OBJC_FUNCDISPATCH4(__kCFStringTypeID, void, string, "getLineStart:end:contentsEnd:forRange:", lineBeginIndex, lineEndIndex, contentsEndIndex, range);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSString *)string, getLineStart:(NSUInteger *)lineBeginIndex end:(NSUInteger *)lineEndIndex contentsEnd:(NSUInteger *)contentsEndIndex forRange:NSMakeRange(range.location, range.length));
__CFStringGetLineOrParagraphBounds(string, range, lineBeginIndex, lineEndIndex, contentsEndIndex, true);
}
void CFStringGetParagraphBounds(CFStringRef string, CFRange range, CFIndex *parBeginIndex, CFIndex *parEndIndex, CFIndex *contentsEndIndex) {
- CF_OBJC_FUNCDISPATCH4(__kCFStringTypeID, void, string, "getParagraphStart:end:contentsEnd:forRange:", parBeginIndex, parEndIndex, contentsEndIndex, range);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSString *)string, getParagraphStart:(NSUInteger *)parBeginIndex end:(NSUInteger *)parEndIndex contentsEnd:(NSUInteger *)contentsEndIndex forRange:NSMakeRange(range.location, range.length));
__CFStringGetLineOrParagraphBounds(string, range, parBeginIndex, parEndIndex, contentsEndIndex, false);
}
if (((encoding & 0x0FFF) == kCFStringEncodingUnicode) && ((encoding == kCFStringEncodingUnicode) || ((encoding > kCFStringEncodingUTF8) && (encoding <= kCFStringEncodingUTF32LE)))) {
guessedByteLength = (length + 1) * ((((encoding >> 26) & 2) == 0) ? sizeof(UTF16Char) : sizeof(UTF32Char)); // UTF32 format has the bit set
} else if (((guessedByteLength = CFStringGetMaximumSizeForEncoding(length, encoding)) > length) && !CF_IS_OBJC(__kCFStringTypeID, string)) { // Multi byte encoding
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
if (__CFStrIsUnicode(string)) {
CFIndex aLength = CFStringEncodingByteLengthForCharacters(encoding, kCFStringEncodingPrependBOM, __CFStrContents(string), __CFStrLength(string));
if (aLength > 0) guessedByteLength = aLength;
if (guessedByteLength == length && __CFStrIsEightBit(string) && __CFStringEncodingIsSupersetOfASCII(encoding)) { // It's all ASCII !!
return CFDataCreate(alloc, ((uint8_t *)__CFStrContents(string) + __CFStrSkipAnyLengthByte(string)), __CFStrLength(string));
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
}
#endif
}
CFStringEncoding CFStringGetSmallestEncoding(CFStringRef str) {
CFIndex len;
- CF_OBJC_FUNCDISPATCH0(__kCFStringTypeID, CFStringEncoding, str, "_smallestEncodingInCFStringEncoding");
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, CFStringEncoding, (NSString *)str, _smallestEncodingInCFStringEncoding);
__CFAssertIsString(str);
if (__CFStrIsEightBit(str)) return __CFStringGetEightBitStringEncoding();
CFStringEncoding CFStringGetFastestEncoding(CFStringRef str) {
- CF_OBJC_FUNCDISPATCH0(__kCFStringTypeID, CFStringEncoding, str, "_fastestEncodingInCFStringEncoding");
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, CFStringEncoding, (NSString *)str, _fastestEncodingInCFStringEncoding);
__CFAssertIsString(str);
return __CFStrIsEightBit(str) ? __CFStringGetEightBitStringEncoding() : kCFStringEncodingUnicode; /* ??? */
}
void CFStringInsert(CFMutableStringRef str, CFIndex idx, CFStringRef insertedStr) {
- CF_OBJC_FUNCDISPATCH2(__kCFStringTypeID, void, str, "insertString:atIndex:", insertedStr, idx);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)str, insertString:(NSString *)insertedStr atIndex:(NSUInteger)idx);
__CFAssertIsStringAndMutable(str);
CFAssert3(idx >= 0 && idx <= __CFStrLength(str), __kCFLogAssertion, "%s(): string index %d out of bounds (length %d)", __PRETTY_FUNCTION__, idx, __CFStrLength(str));
__CFStringReplace(str, CFRangeMake(idx, 0), insertedStr);
void CFStringDelete(CFMutableStringRef str, CFRange range) {
- CF_OBJC_FUNCDISPATCH1(__kCFStringTypeID, void, str, "deleteCharactersInRange:", range);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)str, deleteCharactersInRange:NSMakeRange(range.location, range.length));
__CFAssertIsStringAndMutable(str);
__CFAssertRangeIsInStringBounds(str, range.location, range.length);
__CFStringChangeSize(str, range, 0, false);
void CFStringReplace(CFMutableStringRef str, CFRange range, CFStringRef replacement) {
- CF_OBJC_FUNCDISPATCH2(__kCFStringTypeID, void, str, "replaceCharactersInRange:withString:", range, replacement);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)str, replaceCharactersInRange:NSMakeRange(range.location, range.length) withString:(NSString *)replacement);
__CFAssertIsStringAndMutable(str);
__CFAssertRangeIsInStringBounds(str, range.location, range.length);
__CFStringReplace(str, range, replacement);
void CFStringReplaceAll(CFMutableStringRef str, CFStringRef replacement) {
- CF_OBJC_FUNCDISPATCH1(__kCFStringTypeID, void, str, "setString:", replacement);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)str, setString:(NSString *)replacement);
__CFAssertIsStringAndMutable(str);
__CFStringReplace(str, CFRangeMake(0, __CFStrLength(str)), replacement);
}
void CFStringAppend(CFMutableStringRef str, CFStringRef appended) {
- CF_OBJC_FUNCDISPATCH1(__kCFStringTypeID, void, str, "appendString:", appended);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)str, appendString:(NSString *)appended);
__CFAssertIsStringAndMutable(str);
__CFStringReplace(str, CFRangeMake(__CFStrLength(str), 0), appended);
}
__CFAssertIsNotNegative(appendedLength);
- CF_OBJC_FUNCDISPATCH2(__kCFStringTypeID, void, str, "appendCharacters:length:", chars, appendedLength);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)str, appendCharacters:chars length:(NSUInteger)appendedLength);
__CFAssertIsStringAndMutable(str);
if (CF_IS_OBJC(__kCFStringTypeID, str)) {
if (!appendedIsUnicode && !demoteAppendedUnicode) {
- CF_OBJC_FUNCDISPATCH2(__kCFStringTypeID, void, str, "_cfAppendCString:length:", cStr, appendedLength);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)str, _cfAppendCString:(const unsigned char *)cStr length:(NSInteger)appendedLength);
} else {
- CF_OBJC_FUNCDISPATCH2(__kCFStringTypeID, void, str, "appendCharacters:length:", cStr, appendedLength);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)str, appendCharacters:(const unichar *)cStr length:(NSUInteger)appendedLength);
}
} else {
CFIndex strLength;
CFIndex CFStringFindAndReplace(CFMutableStringRef string, CFStringRef stringToFind, CFStringRef replacementString, CFRange rangeToSearch, CFStringCompareFlags compareOptions) {
- CF_OBJC_FUNCDISPATCH4(__kCFStringTypeID, CFIndex, string, "replaceOccurrencesOfString:withString:options:range:", stringToFind, replacementString, compareOptions, rangeToSearch);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, CFIndex, (NSMutableString *)string, replaceOccurrencesOfString:(NSString *)stringToFind withString:(NSString *)replacementString options:(NSStringCompareOptions)compareOptions range:NSMakeRange(rangeToSearch.location, rangeToSearch.length));
CFRange foundRange;
Boolean backwards = ((compareOptions & kCFCompareBackwards) != 0);
UInt32 endIndex = rangeToSearch.location + rangeToSearch.length;
__CFAssertIsNotNegative(length);
__CFAssertIsNotNegative(indexIntoPad);
- CF_OBJC_FUNCDISPATCH3(__kCFStringTypeID, void, string, "_cfPad:length:padIndex:", padString, length, indexIntoPad);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)string, _cfPad:padString length:(uint32_t)length padIndex:(uint32_t)indexIntoPad);
__CFAssertIsStringAndMutable(string);
CFIndex newStartIndex;
CFIndex length;
- CF_OBJC_FUNCDISPATCH1(__kCFStringTypeID, void, string, "_cfTrim:", trimString);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)string, _cfTrim:trimString);
__CFAssertIsStringAndMutable(string);
__CFAssertIsString(trimString);
CFIndex length;
CFStringInlineBuffer buffer;
- CF_OBJC_FUNCDISPATCH0(__kCFStringTypeID, void, string, "_cfTrimWS");
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)string, _cfTrimWS);
__CFAssertIsStringAndMutable(string);
const uint8_t *langCode;
Boolean isEightBit = __CFStrIsEightBit(string);
- CF_OBJC_FUNCDISPATCH1(__kCFStringTypeID, void, string, "_cfLowercase:", locale);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)string, _cfLowercase:(const void *)locale);
__CFAssertIsStringAndMutable(string);
const uint8_t *langCode;
Boolean isEightBit = __CFStrIsEightBit(string);
- CF_OBJC_FUNCDISPATCH1(__kCFStringTypeID, void, string, "_cfUppercase:", locale);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)string, _cfUppercase:(const void *)locale);
__CFAssertIsStringAndMutable(string);
Boolean isLastCased = false;
const uint8_t *caseIgnorableForBMP;
- CF_OBJC_FUNCDISPATCH1(__kCFStringTypeID, void, string, "_cfCapitalize:", locale);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)string, _cfCapitalize:(const void *)locale);
__CFAssertIsStringAndMutable(string);
CFIndex length;
bool needToReorder = true;
- CF_OBJC_FUNCDISPATCH1(__kCFStringTypeID, void, string, "_cfNormalize:", theForm);
+ CF_OBJC_FUNCDISPATCHV(__kCFStringTypeID, void, (NSMutableString *)string, _cfNormalize:theForm);
__CFAssertIsStringAndMutable(string);
}
}
-void CFStringFold(CFMutableStringRef theString, CFStringCompareFlags theFlags, CFLocaleRef locale) {
+void CFStringFold(CFMutableStringRef theString, CFOptionFlags theFlags, CFLocaleRef locale) {
CFStringInlineBuffer stringBuffer;
CFIndex length = CFStringGetLength(theString);
CFIndex currentIndex = 0;
}
enum {
- kCFStringFormatZeroFlag = (1 << 0), // if not, padding is space char
- kCFStringFormatMinusFlag = (1 << 1), // if not, no flag implied
- kCFStringFormatPlusFlag = (1 << 2), // if not, no flag implied, overrides space
- kCFStringFormatSpaceFlag = (1 << 3), // if not, no flag implied
- kCFStringFormatExternalSpecFlag = (1 << 4) // using config dict
+ kCFStringFormatZeroFlag = (1 << 0), // if not, padding is space char
+ kCFStringFormatMinusFlag = (1 << 1), // if not, no flag implied
+ kCFStringFormatPlusFlag = (1 << 2), // if not, no flag implied, overrides space
+ kCFStringFormatSpaceFlag = (1 << 3), // if not, no flag implied
+ kCFStringFormatExternalSpecFlag = (1 << 4), // using config dict
+ kCFStringFormatLocalizable = (1 << 5) // explicitly mark the specs we can localize
};
typedef struct {
int8_t precArgNum;
int8_t widthArgNum;
int8_t configDictIndex;
+ int8_t numericFormatStyle; // Only set for localizable numeric quantities
} CFFormatSpec;
typedef struct {
CFFormatSizePointer = CFFormatSize4
#endif
};
-
-
+
+enum {
+ CFFormatStyleDecimal = (1 << 0),
+ CFFormatStyleScientific = (1 << 1),
+ CFFormatStyleDecimalOrScientific = CFFormatStyleDecimal|CFFormatStyleScientific,
+ CFFormatStyleUnsigned = (1 << 2)
+};
enum {
CFFormatLiteralType = 32,
CFFormatDummyPointerType = 42 /* special case for %n */
};
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+/* Only come in here if spec->type is CFFormatLongType or CFFormatDoubleType. Pass in 0 for width or precision if not specified. Returns false if couldn't do the format (with the assumption the caller falls back to unlocalized).
+*/
+static Boolean __CFStringFormatLocalizedNumber(CFMutableStringRef output, CFLocaleRef locale, const CFPrintValue *values, const CFFormatSpec *spec, SInt32 width, SInt32 precision, Boolean hasPrecision) {
+ static CFSpinLock_t formatterLock = CFSpinLockInit;
+ // These formatters are recached if the locale argument is different
+ static CFNumberFormatterRef decimalFormatter = NULL;
+ static CFNumberFormatterRef scientificFormatter = NULL;
+ static CFNumberFormatterRef gFormatter = NULL; // for %g
+ static SInt32 groupingSize = 0;
+ static SInt32 secondaryGroupingSize = 0;
+
+ // !!! This code should be removed before shipping
+ static char disableLocalizedFormatting = -1;
+ if (disableLocalizedFormatting == -1) disableLocalizedFormatting = (getenv("CFStringDisableLocalizedNumberFormatting") != NULL) ? 1 : 0;
+ if (disableLocalizedFormatting) return false;
+
+ CFNumberFormatterRef formatter;
+
+ __CFSpinLock(&formatterLock); // We use the formatter from one thread at one time; if this proves to be a bottleneck we need to get fancier
+
+ switch (spec->numericFormatStyle) {
+ case CFFormatStyleUnsigned:
+ case CFFormatStyleDecimal:
+ if (!decimalFormatter || !CFEqual(CFNumberFormatterGetLocale(decimalFormatter), locale)) { // cache or recache if the locale is different
+ if (decimalFormatter) CFRelease(decimalFormatter);
+ decimalFormatter = CFNumberFormatterCreate(NULL, locale, kCFNumberFormatterDecimalStyle); // since this is shared, remember to reset all its properties!
+ }
+ formatter = decimalFormatter;
+ break;
+ case CFFormatStyleScientific:
+ if (!scientificFormatter || !CFEqual(CFNumberFormatterGetLocale(scientificFormatter), locale)) { // cache or recache if the locale is different
+ if (scientificFormatter) CFRelease(scientificFormatter);
+ scientificFormatter = CFNumberFormatterCreate(NULL, locale, kCFNumberFormatterScientificStyle);
+ CFStringRef pattern = CFSTR("#E+00"); // the default pattern does not have the sign if the exponent is positive and it is single digit
+ CFNumberFormatterSetFormat(scientificFormatter, pattern);
+ CFNumberFormatterSetProperty(scientificFormatter, kCFNumberFormatterUseSignificantDigitsKey, kCFBooleanTrue);
+ }
+ formatter = scientificFormatter;
+ break;
+ case CFFormatStyleDecimalOrScientific:
+ if (!gFormatter || !CFEqual(CFNumberFormatterGetLocale(gFormatter), locale)) { // cache or recache if the locale is different
+ if (gFormatter) CFRelease(gFormatter);
+ gFormatter = CFNumberFormatterCreate(NULL, locale, kCFNumberFormatterDecimalStyle);
+ // when we update the locale in gFormatter, we also need to update the two grouping sizes
+ CFNumberRef num = (CFNumberRef) CFNumberFormatterCopyProperty(gFormatter, kCFNumberFormatterGroupingSizeKey);
+ CFNumberGetValue(num, kCFNumberSInt32Type, &groupingSize);
+ CFRelease(num);
+ num = (CFNumberRef) CFNumberFormatterCopyProperty(gFormatter, kCFNumberFormatterSecondaryGroupingSizeKey);
+ CFNumberGetValue(num, kCFNumberSInt32Type, &secondaryGroupingSize);
+ CFRelease(num);
+ }
+ formatter = gFormatter;
+ break;
+ }
+
+ SInt32 prec = hasPrecision ? precision : ((spec->type == CFFormatLongType) ? 0 : 6); // default precision of printf is 6
+
+ // pattern must be set before setting width and padding
+ // otherwise, the pattern will take over those settings
+ if (spec->numericFormatStyle == CFFormatStyleDecimalOrScientific) {
+ if (prec == 0) prec = 1; // at least one sig fig
+ CFMutableStringRef pattern = CFStringCreateMutable(NULL, 0);
+ // use significant digits pattern
+ CFStringAppendCString(pattern, "@", kCFStringEncodingASCII);
+ CFStringPad(pattern, CFSTR("#"), prec, 0);
+ 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
+ }
+#endif
+ double max = pow(10.0, (double)prec); // if the value requires more digits than the number of sig figs, we need to use scientific format
+ double min = 0.0001; // if the value is less than 10E-4, scientific format is the shorter form
+ if (((targetValue > 0 && (targetValue > max || targetValue < min)) || (targetValue < 0 && (targetValue < -max || targetValue > -min)))){
+ CFStringAppendCString(pattern, "E+00", kCFStringEncodingASCII);
+ } else if (prec > groupingSize && groupingSize != 0) {
+ CFStringInsert(pattern, prec-groupingSize, CFSTR(",")); // if we are not using scientific format, we need to set the pattern to use grouping separator
+ if (secondaryGroupingSize != 0 && prec > (groupingSize + secondaryGroupingSize)) CFStringInsert(pattern, prec-groupingSize-secondaryGroupingSize, CFSTR(","));
+ }
+ CFNumberFormatterSetFormat(formatter, pattern);
+ CFRelease(pattern);
+ }
+
+ CFNumberRef tmp;
+
+ 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);
+ }
+ CFRelease(tmp);
+
+
+ // ??? use the right zero here for Arabic
+ Boolean padZero = spec->flags & kCFStringFormatZeroFlag;
+ if (hasPrecision && spec->type == CFFormatLongType) { // if we have precision and %d or %u, we pad 0
+ padZero = true;
+ }
+ CFNumberFormatterSetProperty(formatter, kCFNumberFormatterPaddingCharacterKey, padZero ? CFSTR("0") : CFSTR(" "));
+
+
+ // Left (default) or right padding
+ SInt32 p = (spec->flags & kCFStringFormatMinusFlag) ? kCFNumberFormatterPadAfterSuffix : (padZero ? kCFNumberFormatterPadAfterPrefix : kCFNumberFormatterPadBeforePrefix);
+ if (hasPrecision && spec->type == CFFormatLongType) {
+ SInt32 tmpP = kCFNumberFormatterPadAfterPrefix;
+ tmp = CFNumberCreate(NULL, kCFNumberSInt32Type, &tmpP);
+ } else {
+ tmp = CFNumberCreate(NULL, kCFNumberSInt32Type, &p);
+ }
+ CFNumberFormatterSetProperty(formatter, kCFNumberFormatterPaddingPositionKey, tmp);
+ CFRelease(tmp);
+
+ CFStringRef pattern = CFNumberFormatterGetFormat(formatter);
+ if (spec->flags & kCFStringFormatPlusFlag) {
+ if (CFStringGetCharacterAtIndex(pattern, 0) != '+') {
+ CFMutableStringRef newPattern = CFStringCreateMutableCopy(NULL, 0, CFSTR("+"));
+ CFStringAppend(newPattern, pattern);
+ CFNumberFormatterSetFormat(formatter, newPattern);
+ CFRelease(newPattern);
+ }
+ } else {
+ if (CFStringGetCharacterAtIndex(pattern, 0) == '+') {
+ CFStringRef newPattern = CFStringCreateWithSubstring(NULL, pattern, CFRangeMake(1, CFStringGetLength(pattern)-1));
+ CFNumberFormatterSetFormat(formatter, newPattern);
+ CFRelease(newPattern);
+ }
+ }
+
+ // width == 0 seems to be CFNumberFormatter's default setting
+ if (hasPrecision && spec->type == CFFormatLongType) { // if we have precision and %d or %u, we pad 0 according to precision first
+ tmp = CFNumberCreate(NULL, kCFNumberSInt32Type, &prec);
+ } else {
+ tmp = CFNumberCreate(NULL, kCFNumberSInt32Type, &width);
+ }
+ CFNumberFormatterSetProperty(formatter, kCFNumberFormatterFormatWidthKey, tmp);
+ CFRelease(tmp);
+
+ if (spec->numericFormatStyle == CFFormatStyleScientific) {
+ prec++; // for %e, precision+1 is the number of sig fig
+ tmp = CFNumberCreate(NULL, kCFNumberSInt32Type, &prec);
+ CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMinSignificantDigitsKey, tmp);
+ CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMaxSignificantDigitsKey, tmp);
+ CFRelease(tmp);
+ }
+
+ CFStringRef localizedNumberString = NULL;
+ switch (spec->type) {
+ case CFFormatLongType:
+ // ??? Need to do unsigned
+ localizedNumberString = CFNumberFormatterCreateStringWithValue(NULL, formatter, kCFNumberSInt64Type, &(values[spec->mainArgNum].value.int64Value));
+ break;
+ case CFFormatDoubleType: {
+#if LONG_DOUBLE_SUPPORT
+ if (CFFormatSize16 == values[spec->mainArgNum].size) {
+ double doubleValue = values[spec->mainArgNum].value.longDoubleValue; // losing precision
+ localizedNumberString = CFNumberFormatterCreateStringWithValue(NULL, formatter, kCFNumberDoubleType, &doubleValue);
+ } else
+#endif
+ {
+ localizedNumberString = CFNumberFormatterCreateStringWithValue(NULL, formatter, kCFNumberDoubleType, &(values[spec->mainArgNum].value.doubleValue));
+ }
+ break;
+ }
+ }
+ __CFSpinUnlock(&formatterLock);
+
+ if (localizedNumberString) {
+ // we need to pad space if we have %d or %u
+ if (spec->type == CFFormatLongType && hasPrecision && CFStringGetLength(localizedNumberString) < width) {
+ CFMutableStringRef finalStr = NULL;
+ if (p == kCFNumberFormatterPadAfterSuffix) {
+ finalStr = CFStringCreateMutableCopy(NULL, 0, localizedNumberString);
+ CFStringPad(finalStr, CFSTR(" "), width, 0);
+ } else {
+ finalStr = CFStringCreateMutable(NULL, 0);
+ CFStringPad(finalStr, CFSTR(" "), width - CFStringGetLength(localizedNumberString), 0);
+ CFStringAppend(finalStr, localizedNumberString);
+ }
+ CFRelease(localizedNumberString);
+ localizedNumberString = finalStr;
+ }
+ CFStringAppend(output, localizedNumberString);
+ CFRelease(localizedNumberString);
+ return true;
+ }
+ return false;
+}
+#endif
+
CF_INLINE void __CFParseFormatSpec(const UniChar *uformat, const uint8_t *cformat, SInt32 *fmtIdx, SInt32 fmtLen, CFFormatSpec *spec, CFStringRef *configKeyPointer) {
Boolean seenDot = false;
Boolean seenSharp = false;
spec->flags &= ~kCFStringFormatSpaceFlag; // remove space flag
break;
case '0':
+ if (seenDot) { // after we see '.' and then we see '0', it is 0 precision. We should not see '.' after '0' if '0' is the zero padding flag
+ spec->precArg = 0;
+ break;
+ }
if (!(spec->flags & kCFStringFormatMinusFlag)) spec->flags |= kCFStringFormatZeroFlag;
break;
case 'h':
spec->type = CFFormatLongType;
spec->size = CFFormatSize1;
return;
- case 'O': case 'o': case 'D': case 'd': case 'i': case 'U': case 'u': case 'x': case 'X':
- spec->type = CFFormatLongType;
+ case 'D': case 'd': case 'i': case 'U': case 'u':
+ // we can localize all but octal or hex
+ if (_CFExecutableLinkedOnOrAfter(CFSystemVersionMountainLion)) spec->flags |= kCFStringFormatLocalizable;
+ spec->numericFormatStyle = CFFormatStyleDecimal;
+ if (ch == 'u' || ch == 'U') spec->numericFormatStyle = CFFormatStyleUnsigned;
+ // fall thru
+ case 'O': case 'o': case 'x': case 'X':
+ spec->type = CFFormatLongType;
// Seems like if spec->size == 0, we should spec->size = CFFormatSize4. However, 0 is handled correctly.
return;
- case 'a': case 'A': case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
+ case 'f': case 'F': case 'g': case 'G': case 'e': case 'E': {
+ // we can localize all but hex float output
+ if (_CFExecutableLinkedOnOrAfter(CFSystemVersionMountainLion)) spec->flags |= kCFStringFormatLocalizable;
+ char lch = (ch >= 'A' && ch <= 'Z') ? (ch - 'A' + 'a') : ch;
+ spec->numericFormatStyle = ((lch == 'e' || lch == 'g') ? CFFormatStyleScientific : 0) | ((lch == 'f' || lch == 'g') ? CFFormatStyleDecimal : 0);
+ if (seenDot && spec->precArg == -1 && spec->precArgNum == -1) { // for the cases that we have '.' but no precision followed, not even '*'
+ spec->precArg = 0;
+ }
+ }
+ // fall thru
+ case 'a': case 'A':
spec->type = CFFormatDoubleType;
if (spec->size != CFFormatSize16) spec->size = CFFormatSize8;
return;
case 'n': /* %n is not handled correctly; for Leopard or newer apps, we disable it further */
- spec->type = _CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard) ? CFFormatDummyPointerType : CFFormatPointerType;
+ spec->type = 1 ? CFFormatDummyPointerType : CFFormatPointerType;
spec->size = CFFormatSizePointer; // 4 or 8 depending on LP64
return;
case 'p':
}
}
-/* ??? It ignores the formatOptions argument.
- ??? %s depends on handling of encodings by __CFStringAppendBytes
+/* ??? %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);
}
+
+// Length of the buffer to call sprintf() with
+#define BUFFER_LEN 512
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#define SNPRINTF(TYPE, WHAT) { \
TYPE value = (TYPE) WHAT; \
if (-1 != specs[curSpec].widthArgNum) { \
if (-1 != specs[curSpec].precArgNum) { \
- snprintf_l(buffer, 255, NULL, formatBuffer, width, precision, value); \
+ snprintf_l(buffer, BUFFER_LEN-1, NULL, formatBuffer, width, precision, value); \
} else { \
- snprintf_l(buffer, 255, NULL, formatBuffer, width, value); \
+ snprintf_l(buffer, BUFFER_LEN-1, NULL, formatBuffer, width, value); \
} \
} else { \
if (-1 != specs[curSpec].precArgNum) { \
- snprintf_l(buffer, 255, NULL, formatBuffer, precision, value); \
+ snprintf_l(buffer, BUFFER_LEN-1, NULL, formatBuffer, precision, value); \
} else { \
- snprintf_l(buffer, 255, NULL, formatBuffer, value); \
+ snprintf_l(buffer, BUFFER_LEN-1, NULL, formatBuffer, value); \
} \
}}
#else
const UniChar *uformat = NULL;
UniChar *formatChars = NULL;
UniChar localFormatBuffer[FORMAT_BUFFER_LEN];
-
- #define VPRINTF_BUFFER_LEN 61
+
+#define VPRINTF_BUFFER_LEN 61
CFFormatSpec localSpecsBuffer[VPRINTF_BUFFER_LEN];
CFFormatSpec *specs;
CFPrintValue localValuesBuffer[VPRINTF_BUFFER_LEN];
CFIndex numConfigs;
CFAllocatorRef tmpAlloc = NULL;
intmax_t dummyLocation; // A place for %n to do its thing in; should be the widest possible int value
- va_list copiedArgs;
numSpecs = 0;
sizeSpecs = 0;
if (values != localValuesBuffer && __CFOASafe) __CFSetLastAllocationEventName(values, "CFString (temp)");
memset(values, 0, sizeArgNum * sizeof(CFPrintValue));
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
// va_copy is a C99 extension. No support on Windows
+ va_list copiedArgs;
if (numConfigs > 0) va_copy(copiedArgs, args); // we need to preserve the original state for passing down
-#endif /* DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD */
+#endif
/* Compute values array */
argNum = initialArgPosition;
switch (specs[curSpec].type) {
case CFFormatLongType:
case CFFormatDoubleType:
- case CFFormatPointerType: {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+ if (formatOptions && (specs[curSpec].flags & kCFStringFormatLocalizable) && (CFGetTypeID(formatOptions) == CFLocaleGetTypeID())) { // We have a locale, so we do localized formatting
+ if (__CFStringFormatLocalizedNumber(outputString, (CFLocaleRef)formatOptions, values, &specs[curSpec], width, precision, hasPrecision)) break;
+ }
+ /* Otherwise fall-thru to the next case! */
+#endif
+ case CFFormatPointerType: {
char formatBuffer[128];
#if defined(__GNUC__)
- char buffer[256 + width + precision];
+ char buffer[BUFFER_LEN + width + precision];
#else
- char stackBuffer[512];
+ char stackBuffer[BUFFER_LEN];
char *dynamicBuffer = NULL;
char *buffer = stackBuffer;
- if (256+width+precision > 512) {
+ if (256+width+precision > BUFFER_LEN) {
dynamicBuffer = (char *)CFAllocatorAllocate(kCFAllocatorSystemDefault, 256+width+precision, 0);
buffer = dynamicBuffer;
}
}
// See if we need to localize the decimal point
if (formatOptions) { // We have localization info
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
CFStringRef decimalSeparator = (CFGetTypeID(formatOptions) == CFLocaleGetTypeID()) ? (CFStringRef)CFLocaleGetValue((CFLocaleRef)formatOptions, kCFLocaleDecimalSeparatorKey) : (CFStringRef)CFDictionaryGetValue(formatOptions, CFSTR("NSDecimalSeparator"));
+#else
+ CFStringRef decimalSeparator = CFSTR(".");
+#endif
if (decimalSeparator != NULL) { // We have a decimal separator in there
CFIndex decimalPointLoc = 0;
while (buffer[decimalPointLoc] != 0 && buffer[decimalPointLoc] != '.') decimalPointLoc++;
}
if (!appended) CFStringAppendCString(outputString, (const char *)buffer, __CFStringGetEightBitStringEncoding());
#if !defined(__GNUC__)
- if (dynamicBuffer) {
- CFAllocatorDeallocate(kCFAllocatorSystemDefault, dynamicBuffer);
- }
+ if (dynamicBuffer) {
+ CFAllocatorDeallocate(kCFAllocatorSystemDefault, dynamicBuffer);
+ }
#endif
- }
- break;
+ }
+ break;
case CFFormatLiteralType:
if (cformat) {
__CFStringAppendBytes(outputString, (const char *)(cformat+specs[curSpec].loc), specs[curSpec].len, __CFStringGetEightBitStringEncoding());
}
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
// va_copy is a C99 extension. No support on Windows
if (numConfigs > 0) va_end(copiedArgs);
-#endif /* DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD */
+#endif
if (specs != localSpecsBuffer) CFAllocatorDeallocate(tmpAlloc, specs);
if (values != localValuesBuffer) CFAllocatorDeallocate(tmpAlloc, values);
if (formatChars && (formatChars != localFormatBuffer)) CFAllocatorDeallocate(tmpAlloc, formatChars);
*/
/* CFString.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFSTRING__)
#include <CoreFoundation/CFLocale.h>
#include <stdarg.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
/*
Call CFStringGetSystemEncoding() to get the default system encoding.
*/
#define kCFStringEncodingInvalidId (0xffffffffU)
-enum {
+typedef CF_ENUM(CFStringEncoding, CFStringBuiltInEncodings) {
kCFStringEncodingMacRoman = 0,
kCFStringEncodingWindowsLatin1 = 0x0500, /* ANSI codepage 1252 */
kCFStringEncodingISOLatin1 = 0x0201, /* ISO 8859-1 */
kCFStringEncodingUTF32BE = 0x18000100, /* kTextEncodingUnicodeDefault + kUnicodeUTF32BEFormat */
kCFStringEncodingUTF32LE = 0x1c000100 /* kTextEncodingUnicodeDefault + kUnicodeUTF32LEFormat */
};
-typedef CFStringEncoding CFStringBuiltInEncodings;
/* CFString type ID */
/* Find and compare flags; these are OR'ed together and provided as CFStringCompareFlags in the various functions.
*/
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFStringCompareFlags) {
kCFCompareCaseInsensitive = 1,
kCFCompareBackwards = 4, /* Starting from the end of the string */
kCFCompareAnchored = 8, /* Only at the specified starting point */
kCFCompareNonliteral = 16, /* If specified, loose equivalence is performed (o-umlaut == o, umlaut) */
kCFCompareLocalized = 32, /* User's default locale is used for the comparisons */
- kCFCompareNumerically = 64 /* Numeric comparison is used; that is, Foo2.txt < Foo7.txt < Foo25.txt */
-#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
- ,
- kCFCompareDiacriticInsensitive = 128, /* If specified, ignores diacritics (o-umlaut == o) */
- kCFCompareWidthInsensitive = 256, /* If specified, ignores width differences ('a' == UFF41) */
- kCFCompareForcedOrdering = 512 /* If specified, comparisons are forced to return either kCFCompareLessThan or kCFCompareGreaterThan if the strings are equivalent but not strictly equal, for stability when sorting (e.g. "aaa" > "AAA" with kCFCompareCaseInsensitive specified) */
-#endif /* MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED */
+ kCFCompareNumerically = 64, /* Numeric comparison is used; that is, Foo2.txt < Foo7.txt < Foo25.txt */
+ kCFCompareDiacriticInsensitive CF_ENUM_AVAILABLE(10_5, 2_0) = 128, /* If specified, ignores diacritics (o-umlaut == o) */
+ kCFCompareWidthInsensitive CF_ENUM_AVAILABLE(10_5, 2_0) = 256, /* If specified, ignores width differences ('a' == UFF41) */
+ kCFCompareForcedOrdering CF_ENUM_AVAILABLE(10_5, 2_0) = 512 /* If specified, comparisons are forced to return either kCFCompareLessThan or kCFCompareGreaterThan if the strings are equivalent but not strictly equal, for stability when sorting (e.g. "aaa" > "AAA" with kCFCompareCaseInsensitive specified) */
};
-typedef CFOptionFlags CFStringCompareFlags;
/* The main comparison routine; compares specified range of the first string to (the full range of) the second string.
locale == NULL indicates canonical locale (the return value from CFLocaleGetSystem()).
Unicode Technical Report #15. To normalize for use with file
system calls, use CFStringGetFileSystemRepresentation().
*/
-enum {
+typedef CF_ENUM(CFIndex, CFStringNormalizationForm) {
kCFStringNormalizationFormD = 0, // Canonical Decomposition
kCFStringNormalizationFormKD, // Compatibility Decomposition
kCFStringNormalizationFormC, // Canonical Decomposition followed by Canonical Composition
kCFStringNormalizationFormKC // Compatibility Decomposition followed by Canonical Composition
};
-typedef CFIndex CFStringNormalizationForm;
/*!
@function CFStringNormalize
CFStringRef __CFStringMakeConstantString(const char *cStr); /* Private; do not use */
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFSTRING__ */
*/
/* CFStringDefaultEncoding.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFSTRINGDEFAULTENCODING__)
*/
/* CFStringEncodingConverter.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Aki Inoue
*/
#include "CFStringEncodingConverterExt.h"
#include "CFStringEncodingConverterPriv.h"
#include <stdlib.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#include <pthread.h>
-#endif
typedef CFIndex (*_CFToBytesProc)(const void *converter, uint32_t flags, const UniChar *characters, CFIndex numChars, uint8_t *bytes, CFIndex maxByteLen, CFIndex *usedByteLen);
typedef CFIndex (*_CFToUnicodeProc)(const void *converter, uint32_t flags, const uint8_t *bytes, CFIndex numBytes, UniChar *characters, CFIndex maxCharLen, CFIndex *usedCharLen);
converter->toCanonicalUnicode = __CFToCanonicalUnicodeCheapMultiByteWrapper;
break;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
case kCFStringEncodingConverterICU:
converter->toBytes = (_CFToBytesProc)__CFStringEncodingGetICUName(encoding);
break;
+#endif
case kCFStringEncodingConverterPlatformSpecific:
break;
case kCFStringEncodingUTF8: commonConverterSlot = (const _CFEncodingConverter **)&(commonConverters[0]); break;
/* the swith here should avoid possible bootstrap issues in the default: case below when invoked from CFStringGetSystemEncoding() */
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
case kCFStringEncodingMacRoman: commonConverterSlot = (const _CFEncodingConverter **)&(commonConverters[1]); break;
#elif DEPLOYMENT_TARGET_WINDOWS
case kCFStringEncodingWindowsLatin1: commonConverterSlot = (const _CFEncodingConverter **)(&(commonConverters[1])); break;
#else
#warning This case must match __defaultEncoding value defined in CFString.c
case kCFStringEncodingISOLatin1: commonConverterSlot = (const _CFEncodingConverter **)(&(commonConverters[1])); break;
-#endif /* DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED */
+#endif
default: if (CFStringGetSystemEncoding() == encoding) commonConverterSlot = (const _CFEncodingConverter **)&(commonConverters[2]); break;
}
}
}
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (kCFStringEncodingConverterICU == converter->definition->encodingClass) return __CFStringEncodingICUToBytes((const char *)converter->toBytes, flags, characters, numChars, usedCharLen, bytes, maxByteLen, usedByteLen);
+#endif
/* Platform converter */
if (kCFStringEncodingConverterPlatformSpecific == converter->definition->encodingClass) return __CFStringEncodingPlatformUnicodeToBytes(encoding, flags, characters, numChars, usedCharLen, bytes, maxByteLen, usedByteLen);
if (!converter) return kCFStringEncodingConverterUnavailable;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (kCFStringEncodingConverterICU == converter->definition->encodingClass) return __CFStringEncodingICUToUnicode((const char *)converter->toBytes, flags, bytes, numBytes, usedByteLen, characters, maxCharLen, usedCharLen);
+#endif
/* Platform converter */
if (kCFStringEncodingConverterPlatformSpecific == converter->definition->encodingClass) return __CFStringEncodingPlatformBytesToUnicode(encoding, flags, bytes, numBytes, usedByteLen, characters, maxCharLen, usedCharLen);
const _CFEncodingConverter *converter = __CFGetConverter(encoding);
if (converter) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (kCFStringEncodingConverterICU == converter->definition->encodingClass) return __CFStringEncodingICUCharLength((const char *)converter->toBytes, flags, bytes, numBytes);
-
+#endif
+
if (kCFStringEncodingConverterPlatformSpecific == converter->definition->encodingClass) return __CFStringEncodingPlatformCharLengthForBytes(encoding, flags, bytes, numBytes);
if (1 == converter->definition->maxBytesPerChar) return numBytes;
const _CFEncodingConverter *converter = __CFGetConverter(encoding);
if (converter) {
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (kCFStringEncodingConverterICU == converter->definition->encodingClass) return __CFStringEncodingICUByteLength((const char *)converter->toBytes, flags, characters, numChars);
+#endif
if (kCFStringEncodingConverterPlatformSpecific == converter->definition->encodingClass) return __CFStringEncodingPlatformByteLengthForCharacters(encoding, flags, characters, numChars);
if (NULL == encodings) {
CFStringEncoding *list = (CFStringEncoding *)__CFBuiltinEncodings;
CFIndex numICUConverters = 0, numPlatformConverters = 0;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
CFStringEncoding *icuConverters = __CFStringEncodingCreateICUEncodings(NULL, &numICUConverters);
+#else
+ CFStringEncoding *icuConverters = NULL;
+#endif
CFStringEncoding *platformConverters = __CFStringEncodingCreateListOfAvailablePlatformConverters(NULL, &numPlatformConverters);
if ((NULL != icuConverters) || (NULL != platformConverters)) {
*/
/* CFStringEncodingConverter.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFSTRINGENCODINGCONVERTER__)
*/
/* CFStringEncodingConverterExt.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFSTRINGENCODINGCONVERETEREXT__)
*/
/* CFStringEncodingConverterPriv.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFSTRINGENCODINGCONVERTERPRIV__)
*/
/* CFStringEncodingDatabase.c
- Copyright (c) 2005-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2005-2012, Apple Inc. All rights reserved.
Responsibility: Aki Inoue
*/
* CoreFoundation
*
* Created by Aki Inoue on 07/12/05.
- * Copyright (c) 2007-2011, Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2012, Apple Inc. All rights reserved.
*
*/
*/
/* CFStringEncodingExt.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFSTRINGENCODINGEXT__)
CF_EXTERN_C_BEGIN
-enum {
+typedef CF_ENUM(CFIndex, CFStringEncodings) {
/* kCFStringEncodingMacRoman = 0L, defined in CoreFoundation/CFString.h */
kCFStringEncodingMacJapanese = 1,
kCFStringEncodingMacChineseTrad = 2,
kCFStringEncodingJIS_X0208_90 = 0x0622,
kCFStringEncodingJIS_X0212_90 = 0x0623,
kCFStringEncodingJIS_C6226_78 = 0x0624,
-#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
- kCFStringEncodingShiftJIS_X0213 = 0x0628, /* Shift-JIS format encoding of JIS X0213 planes 1 and 2*/
-#endif
+ kCFStringEncodingShiftJIS_X0213 CF_ENUM_AVAILABLE(10_5, 2_0) = 0x0628, /* Shift-JIS format encoding of JIS X0213 planes 1 and 2*/
kCFStringEncodingShiftJIS_X0213_MenKuTen = 0x0629, /* JIS X0213 in plane-row-column notation */
kCFStringEncodingGB_2312_80 = 0x0630,
kCFStringEncodingGBK_95 = 0x0631, /* annex to GB 13000-93; for Windows 95 */
kCFStringEncodingEBCDIC_US = 0x0C01, /* basic EBCDIC-US */
kCFStringEncodingEBCDIC_CP037 = 0x0C02, /* code page 037, extended EBCDIC (Latin-1 set) for US,Canada... */
-#if MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED
- kCFStringEncodingUTF7 = 0x04000100, /* kTextEncodingUnicodeDefault + kUnicodeUTF7Format RFC2152 */
- kCFStringEncodingUTF7_IMAP = 0x0A10, /* UTF-7 (IMAP folder variant) RFC3501 */
-#endif /* MAC_OS_X_VERSION_10_6 <= MAC_OS_X_VERSION_MAX_ALLOWED */
+ kCFStringEncodingUTF7 CF_ENUM_AVAILABLE(10_6, 4_0) = 0x04000100, /* kTextEncodingUnicodeDefault + kUnicodeUTF7Format RFC2152 */
+ kCFStringEncodingUTF7_IMAP CF_ENUM_AVAILABLE(10_6, 4_0) = 0x0A10, /* UTF-7 (IMAP folder variant) RFC3501 */
/* Deprecated constants */
kCFStringEncodingShiftJIS_X0213_00 = 0x0628 /* Shift-JIS format encoding of JIS X0213 planes 1 and 2 (DEPRECATED) */
};
-typedef CFIndex CFStringEncodings;
CF_EXTERN_C_END
*/
/* CFStringEncodings.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Aki Inoue
*/
#include <CoreFoundation/CFStringDefaultEncoding.h>
#endif
-static UInt32 __CFWantsToUseASCIICompatibleConversion = (UInt32)-1;
-CF_INLINE UInt32 __CFGetASCIICompatibleFlag(void) {
- if (__CFWantsToUseASCIICompatibleConversion == (UInt32)-1) {
- __CFWantsToUseASCIICompatibleConversion = false;
- }
- return (__CFWantsToUseASCIICompatibleConversion ? kCFStringEncodingASCIICompatibleConversion : 0);
-}
+static bool __CFWantsToUseASCIICompatibleConversion = false;
+CF_INLINE UInt32 __CFGetASCIICompatibleFlag(void) { return __CFWantsToUseASCIICompatibleConversion; }
void _CFStringEncodingSetForceASCIICompatibility(Boolean flag) {
__CFWantsToUseASCIICompatibleConversion = (flag ? (UInt32)true : (UInt32)false);
bool swap = false;
static bool strictUTF32 = (bool)-1;
- if ((bool)-1 == strictUTF32) strictUTF32 = (_CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard) != 0);
+ if ((bool)-1 == strictUTF32) strictUTF32 = (1 != 0);
if (kCFStringEncodingUTF32 == encoding) {
UTF32Char bom = ((*src == 0xFFFE0000) || (*src == 0x0000FEFF) ? *(src++) : 0);
*/
/* CFStringScanner.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Ali Ozer
*/
*/
/* CFStringUtilities.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Aki Inoue
*/
#include <CoreFoundation/CFStringEncodingExt.h>
#include "CFStringEncodingDatabase.h"
#include "CFICUConverters.h"
-#include <CoreFoundation/CFPreferences.h>
#include <limits.h>
#include <stdlib.h>
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
#include <unicode/ucol.h>
#include <unicode/ucoleitr.h>
+#endif
#include <string.h>
#if DEPLOYMENT_TARGET_WINDOWS
encoding = __CFStringEncodingGetFromCanonicalName(name);
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if (kCFStringEncodingInvalidId == encoding) encoding = __CFStringEncodingGetFromICUName(name);
-
+#endif
+
return encoding;
}
#define kCFStringCompareAllocationIncrement (128)
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
// -------------------------------------------------------------------------------------------------
// CompareSpecials - ignore case & diacritic differences
return 0; // noErr
}
+#endif // DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
+
static inline CFIndex __extendLocationBackward(CFIndex location, CFStringInlineBuffer *str, const uint8_t *nonBaseBMP, const uint8_t *punctBMP) {
while (location > 0) {
UTF32Char ch = CFStringGetCharacterFromInlineBuffer(str, location);
CFRange range1 = str1Range;
CFRange range2 = str2Range;
SInt32 order;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
Boolean isEqual;
bool forcedOrdering = ((options & kCFCompareForcedOrdering) ? true : false);
UCollator *collator = NULL;
bool defaultCollator = true;
+#endif
static const uint8_t *alnumBMP = NULL;
static const uint8_t *nonBaseBMP = NULL;
static const uint8_t *punctBMP = NULL;
range2.location = __extendLocationBackward(range2.location - 1, str2, nonBaseBMP, punctBMP);
}
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
// First we try to use the last one used on this thread, if the locale is the same,
// otherwise we try to check out a default one, or then we create one.
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
}
#endif
-
+#endif
+
characters1 = CFStringGetCharactersPtrFromInlineBuffer(str1, range1);
characters2 = CFStringGetCharactersPtrFromInlineBuffer(str2, range2);
range1.length = (str1Range.location + str1Range.length) - range1.location;
range2.length = (str2Range.location + str2Range.length) - range2.location;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if ((NULL != collator) && (__CompareTextDefault(collator, options, characters1, range1.length, characters2, range2.length, &isEqual, &order) == 0 /* noErr */)) {
compResult = ((isEqual && !forcedOrdering) ? kCFCompareEqualTo : ((order < 0) ? kCFCompareLessThan : kCFCompareGreaterThan));
- } else {
+ } else
+#endif
+ {
compResult = ((memcmp(characters1, characters2, sizeof(UniChar) * range1.length) < 0) ? kCFCompareLessThan : kCFCompareGreaterThan);
}
} else {
}
}
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
if ((NULL != collator) && (__CompareTextDefault(collator, options, characters1, range1.length, characters2, range2.length, &isEqual, &order) == 0 /* noErr */)) {
if (isEqual) {
if (forcedOrdering && (kCFCompareEqualTo == compResult) && (0 != order)) compResult = ((order < 0) ? kCFCompareLessThan : kCFCompareGreaterThan);
order = 0;
}
- } else {
+ } else
+#endif
+ {
order = memcmp(characters1, characters2, sizeof(UTF16Char) * ((range1.length < range2.length) ? range1.length : range2.length));
if (0 == order) {
if (range1.length < range2.length) {
_CFSetTSD(__CFTSDKeyCollatorLocale, (void *)CFRetain(compareLocale), NULL);
}
#endif
-
+
return compResult;
}
*/
/* CFSystemDirectories.c
- Copyright (c) 1997-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1997-2012, Apple Inc. All rights reserved.
Responsibility: Kevin Perry
*/
*/
/* CFTimeZone.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
if (NULL != tzName) {
tempURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, tzName, false);
if (NULL != tempURL) {
- if (_CFReadBytesFromFile(kCFAllocatorSystemDefault, tempURL, &bytes, &length, 0)) {
+ if (_CFReadBytesFromFile(kCFAllocatorSystemDefault, tempURL, &bytes, &length, 0, 0)) {
data = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, bytes, length, kCFAllocatorSystemDefault);
}
CFRelease(tempURL);
tzName = name;
tempURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, tzName, false);
if (NULL != tempURL) {
- if (_CFReadBytesFromFile(kCFAllocatorSystemDefault, tempURL, &bytes, &length, 0)) {
+ if (_CFReadBytesFromFile(kCFAllocatorSystemDefault, tempURL, &bytes, &length, 0, 0)) {
data = CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault, bytes, length, kCFAllocatorSystemDefault);
}
CFRelease(tempURL);
}
CFStringRef CFTimeZoneGetName(CFTimeZoneRef tz) {
- CF_OBJC_FUNCDISPATCH0(CFTimeZoneGetTypeID(), CFStringRef, tz, "name");
+ CF_OBJC_FUNCDISPATCHV(CFTimeZoneGetTypeID(), CFStringRef, (NSTimeZone *)tz, name);
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
return tz->_name;
}
CFDataRef CFTimeZoneGetData(CFTimeZoneRef tz) {
- CF_OBJC_FUNCDISPATCH0(CFTimeZoneGetTypeID(), CFDataRef, tz, "data");
+ CF_OBJC_FUNCDISPATCHV(CFTimeZoneGetTypeID(), CFDataRef, (NSTimeZone *)tz, data);
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
return tz->_data;
}
}
CFTimeInterval CFTimeZoneGetDaylightSavingTimeOffset(CFTimeZoneRef tz, CFAbsoluteTime at) {
- CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFTimeInterval, tz, "_daylightSavingTimeOffsetForAbsoluteTime:", at);
+ CF_OBJC_FUNCDISPATCHV(CFTimeZoneGetTypeID(), CFTimeInterval, (NSTimeZone *)tz, _daylightSavingTimeOffsetForAbsoluteTime:at);
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
CFIndex idx = __CFBSearchTZPeriods(tz, at);
if (__CFTZPeriodIsDST(&(tz->_periods[idx]))) {
}
CFAbsoluteTime CFTimeZoneGetNextDaylightSavingTimeTransition(CFTimeZoneRef tz, CFAbsoluteTime at) {
- CF_OBJC_FUNCDISPATCH1(CFTimeZoneGetTypeID(), CFTimeInterval, tz, "_nextDaylightSavingTimeTransitionAfterAbsoluteTime:", at);
+ CF_OBJC_FUNCDISPATCHV(CFTimeZoneGetTypeID(), CFTimeInterval, (NSTimeZone *)tz, _nextDaylightSavingTimeTransitionAfterAbsoluteTime:at);
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
CFIndex idx = __CFBSearchTZPeriods(tz, at);
if (tz->_periodCnt <= idx + 1) {
#define BUFFER_SIZE 768
CFStringRef CFTimeZoneCopyLocalizedName(CFTimeZoneRef tz, CFTimeZoneNameStyle style, CFLocaleRef locale) {
- CF_OBJC_FUNCDISPATCH2(CFTimeZoneGetTypeID(), CFStringRef, tz, "localizedName:locale:", style, locale);
+ CF_OBJC_FUNCDISPATCHV(CFTimeZoneGetTypeID(), CFStringRef, (NSTimeZone *)tz, localizedName:(NSTimeZoneNameStyle)style locale:(NSLocale *)locale);
__CFGenericValidateType(tz, CFTimeZoneGetTypeID());
__CFGenericValidateType(locale, CFLocaleGetTypeID());
*/
/* CFTimeZone.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFTIMEZONE__)
#include <CoreFoundation/CFDictionary.h>
#include <CoreFoundation/CFString.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
CF_EXPORT
CF_EXPORT
CFAbsoluteTime CFTimeZoneGetNextDaylightSavingTimeTransition(CFTimeZoneRef tz, CFAbsoluteTime at) CF_AVAILABLE(10_5, 2_0);
-#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
-enum {
+typedef CF_ENUM(CFIndex, CFTimeZoneNameStyle) {
kCFTimeZoneNameStyleStandard,
kCFTimeZoneNameStyleShortStandard,
kCFTimeZoneNameStyleDaylightSaving,
kCFTimeZoneNameStyleShortDaylightSaving,
kCFTimeZoneNameStyleGeneric,
kCFTimeZoneNameStyleShortGeneric
-};
-#endif
-typedef CFIndex CFTimeZoneNameStyle;
+} CF_ENUM_AVAILABLE(10_5, 2_0);
CF_EXPORT
CFStringRef CFTimeZoneCopyLocalizedName(CFTimeZoneRef tz, CFTimeZoneNameStyle style, CFLocaleRef locale) CF_AVAILABLE(10_5, 2_0);
const CFStringRef kCFTimeZoneSystemTimeZoneDidChangeNotification CF_AVAILABLE(10_5, 2_0);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFTIMEZONE__ */
*/
/* CFTree.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
static void __CFTreeDeallocate(CFTypeRef cf) {
CFTreeRef tree = (CFTreeRef)cf;
const struct __CFTreeCallBacks *cb;
+#if DEPLOYMENT_TARGET_MACOSX
CFAllocatorRef allocator = __CFGetAllocator(tree);
if (!CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
// GC: keep the tree intact during finalization.
CFTreeRemoveAllChildren(tree);
}
+#endif
cb = __CFTreeGetCallBacks(tree);
if (NULL != cb->release) {
INVOKE_CALLBACK1(cb->release, tree->_info);
*/
/* CFTree.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
/*!
@header CFTree
#include <CoreFoundation/CFBase.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
/*!
void CFTreeSortChildren(CFTreeRef tree, CFComparatorFunction comparator, void *context);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFTREE__ */
*/
/* CFURL.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: John Iarocci
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#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 DEPLOYMENT_TARGET_MACOSX
#include <CoreFoundation/CFNumberFormatter.h>
#endif
#include <CoreFoundation/CFURLPriv.h>
#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);
#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);
CFStringRef CFURLCreateStringWithFileSystemPath(CFAllocatorRef allocator, CFURLRef anURL, CFURLPathStyle fsType, Boolean resolveAgainstBase);
CF_EXPORT CFURLRef _CFURLCreateCurrentDirectoryURL(CFAllocatorRef allocator);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-static CFStringRef HFSPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir);
+#if DEPLOYMENT_TARGET_MACOSX
+static Boolean _CFURLHasFileURLScheme(CFURLRef url, Boolean *hasScheme);
#endif
+
#ifndef DEBUG_URL_MEMORY_USAGE
#define DEBUG_URL_MEMORY_USAGE 0
#endif
#if DEBUG_URL_MEMORY_USAGE
-static CFAllocatorRef URLAllocator = NULL;
-static UInt32 numFileURLsCreated = 0;
-static UInt32 numFileURLsConverted = 0;
-static UInt32 numFileURLsDealloced = 0;
static UInt32 numURLs = 0;
static UInt32 numDealloced = 0;
+static UInt32 numFileURLsCreated = 0;
static UInt32 numExtraDataAllocated = 0;
static UInt32 numURLsWithBaseURL = 0;
static UInt32 numNonUTF8EncodedURLs = 0;
#endif
/* The bit flags in myURL->_flags */
-#define HAS_SCHEME (0x0001)
-#define HAS_USER (0x0002)
-#define HAS_PASSWORD (0x0004)
-#define HAS_HOST (0x0008)
-#define HAS_PORT (0x0010)
-#define HAS_PATH (0x0020)
-#define HAS_PARAMETERS (0x0040)
-#define HAS_QUERY (0x0080)
-#define HAS_FRAGMENT (0x0100)
-#define HAS_HTTP_SCHEME (0x0200)
-// Last free bit (0x200) in lower word goes here!
-#define IS_IPV6_ENCODED (0x0400)
-#define IS_OLD_UTF8_STYLE (0x0800)
-#define IS_DIRECTORY (0x1000)
-#define IS_PARSED (0x2000)
-#define IS_ABSOLUTE (0x4000)
-#define IS_DECOMPOSABLE (0x8000)
-
-#define PATH_TYPE_MASK (0x000F0000)
-/* POSIX_AND_URL_PATHS_MATCH will only be true if the URL and POSIX paths are identical, character for character, except for the presence/absence of a trailing slash on directories */
-#define POSIX_AND_URL_PATHS_MATCH (0x00100000)
-#define ORIGINAL_AND_URL_STRINGS_MATCH (0x00200000)
-
-/* If ORIGINAL_AND_URL_STRINGS_MATCH is false, these bits determine where they differ */
-// Scheme can actually never differ because if there were escaped characters prior to the colon, we'd interpret the string as a relative path
-// #define SCHEME_DIFFERS (0x00400000) unused
-#define USER_DIFFERS (0x00800000)
-#define PASSWORD_DIFFERS (0x01000000)
-#define HOST_DIFFERS (0x02000000)
-// Port can actually never differ because if there were a non-digit following a colon in the net location, we'd interpret the whole net location as the host
-#define PORT_DIFFERS (0x04000000)
-// #define PATH_DIFFERS (0x08000000) unused
-// #define PARAMETERS_DIFFER (0x10000000) unused
-// #define QUERY_DIFFERS (0x20000000) unused
-#define PATH_HAS_FILE_ID (0x40000000)
-#define HAS_FILE_SCHEME (0x80000000)
-
-// Number of bits to shift to get from HAS_FOO to FOO_DIFFERS flag
-#define BIT_SHIFT_FROM_COMPONENT_TO_DIFFERS_FLAG (22)
+// component bits
+#define HAS_SCHEME (0x00000001)
+#define HAS_USER (0x00000002)
+#define HAS_PASSWORD (0x00000004)
+#define HAS_HOST (0x00000008)
+#define HAS_PORT (0x00000010)
+#define HAS_PATH (0x00000020)
+#define HAS_PARAMETERS (0x00000040)
+#define HAS_QUERY (0x00000080)
+#define HAS_FRAGMENT (0x00000100)
+// various boolean flags
+#define IS_IPV6_ENCODED (0x00000400)
+#define IS_DIRECTORY (0x00000800)
+#define IS_CANONICAL_FILE_URL (0x00001000)
+#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)
+// scheme bits and amount to shift it to translate to the kXXXXScheme enums
+#define SCHEME_TYPE_MASK (0xE0000000)
+#define SCHEME_SHIFT 29
+enum {
+ kHasUncommonScheme = 0,
+ kHasHttpScheme = 1,
+ kHasHttpsScheme = 2,
+ kHasFileScheme = 3,
+ kHasDataScheme = 4,
+ kHasFtpScheme = 5,
+ kMaxScheme
+};
+// accessors for the scheme bits in _flags
+CF_INLINE UInt32 _getSchemeTypeFromFlags(UInt32 flags);
+CF_INLINE void _setSchemeTypeInFlags(UInt32 *flags, UInt32 schemeType);
// Other useful defines
#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.
+// 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 )
+
+// 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)
-/* URL_PATH_TYPE(anURL) will be one of the CFURLPathStyle constants, in which case string is a file system path, or will be FULL_URL_REPRESENTATION, in which case the string is the full URL string. One caveat - string always has a trailing path delimiter if the url is a directory URL. This must be stripped before returning file system representations! */
-#define URL_PATH_TYPE(url) (((url->_flags) & PATH_TYPE_MASK) >> 16)
-#define PATH_DELIM_FOR_TYPE(fsType) ((fsType) == kCFURLHFSPathStyle ? ':' : (((fsType) == kCFURLWindowsPathStyle) ? '\\' : '/'))
-#define PATH_DELIM_AS_STRING_FOR_TYPE(fsType) ((fsType) == kCFURLHFSPathStyle ? CFSTR(":") : (((fsType) == kCFURLWindowsPathStyle) ? CFSTR("\\") : CFSTR("/")))
+/* The bit flags in _CFURLAdditionalData->_additionalDataFlags */
+/* If ORIGINAL_AND_URL_STRINGS_MATCH in myURL->_flags is false, these bits determine where they differ. XXXX_DIFFERS must match the HAS_XXXX */
+#define SCHEME_DIFFERS HAS_SCHEME // Scheme can actually never differ because if there were escaped characters prior to the colon, we'd interpret the string as a relative path
+#define USER_DIFFERS HAS_USER
+#define PASSWORD_DIFFERS HAS_PASSWORD
+#define HOST_DIFFERS HAS_HOST
+#define PORT_DIFFERS HAS_PORT // Port can actually never differ because if there were a non-digit following a colon in the net location, we'd interpret the whole net location as the host
+#define PATH_DIFFERS HAS_PATH // unused
+#define PARAMETERS_DIFFER HAS_PARAMETERS // unused
+#define QUERY_DIFFER HAS_QUERY // unused
+#define FRAGMENT_DIFFER HAS_FRAGMENT // unused
#define FILE_ID_PREFIX ".file"
#define FILE_ID_KEY "id"
#define FILE_ID_PREAMBLE "/.file/id="
#define FILE_ID_PREAMBLE_LENGTH 10
-#define ASSERT_CHECK_PATHSTYLE(x) 0
-
-#if DEPLOYMENT_TARGET_WINDOWS
-#define PATH_SEP '\\'
-#define PATH_MAX MAX_PATH
-#else
-#define PATH_SEP '/'
-#endif
+#define FILE_PREFIX "file://"
+#define FILE_PREFIX_WITH_AUTHORITY "file://localhost"
+static const UInt8 fileURLPrefixWithAuthority[] = FILE_PREFIX_WITH_AUTHORITY;
// 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.
struct _CFURLAdditionalData {
void *_reserved; // Reserved for URLHandle's use.
- CFMutableStringRef _sanitizedString; // The fully compliant RFC string. This is only non-NULL if ORIGINAL_AND_URL_STRINGS_MATCH is false. This should never be mutated except when the sanatized string is first computed
- CFHashCode hashValue;
+ CFStringRef _sanitizedString; // The fully compliant RFC string. This is only non-NULL if ORIGINAL_AND_URL_STRINGS_MATCH is false.
+ UInt32 _additionalDataFlags; // these flags only apply to things we need to keep state for in _CFURLAdditionalData (like the XXXX_DIFFERS flags)
};
struct __CFURL {
CFRuntimeBase _cfBase;
UInt32 _flags;
- CFStringEncoding _encoding; // The encoding to use when asked to remove percent escapes; this is never consulted if IS_OLD_UTF8_STYLE is set.
- CFStringRef _string; // Never NULL; the meaning of _string depends on URL_PATH_TYPE(myURL) (see above)
+ CFStringEncoding _encoding; // The encoding to use when asked to remove percent escapes
+ CFStringRef _string; // Never NULL
CFURLRef _base;
- CFRange *ranges;
- struct _CFURLAdditionalData* extra;
+ CFRange *_ranges;
+ struct _CFURLAdditionalData* _extra;
void *_resourceInfo; // For use by CarbonCore to cache property values. Retained and released by CFURL.
};
CF_INLINE void* _getReserved ( const struct __CFURL* url )
{
- if ( url && url->extra )
- return url->extra->_reserved;
-
- return NULL;
+ if ( url && url->_extra ) {
+ return ( url->_extra->_reserved );
+ }
+ else {
+ return ( NULL );
+ }
}
-CF_INLINE CFMutableStringRef _getSanitizedString ( const struct __CFURL* url )
+CF_INLINE CFStringRef _getSanitizedString(const struct __CFURL* url)
{
- if ( url && url->extra )
- return url->extra->_sanitizedString;
+ if ( url && url->_extra ) {
+ return ( url->_extra->_sanitizedString );
+ }
+ else {
+ return ( NULL );
+ }
+}
- return NULL;
+CF_INLINE UInt32 _getAdditionalDataFlags(const struct __CFURL* url)
+{
+ if ( url && url->_extra ) {
+ return ( url->_extra->_additionalDataFlags );
+ }
+ else {
+ return ( 0 );
+ }
}
-static void* _getResourceInfo ( const struct __CFURL* url )
+CF_INLINE void* _getResourceInfo ( const struct __CFURL* url )
{
if ( url ) {
return url->_resourceInfo;
}
-
- return NULL;
+ else {
+ return NULL;
+ }
}
static void _CFURLAllocateExtraDataspace( struct __CFURL* url )
{
- if ( url && ! url->extra )
+ if ( url && ! url->_extra )
{ struct _CFURLAdditionalData* extra = (struct _CFURLAdditionalData*) CFAllocatorAllocate( CFGetAllocator( url), sizeof( struct _CFURLAdditionalData ), __kCFAllocatorGCScannedMemory);
extra->_reserved = _getReserved( url );
- extra->_sanitizedString = _getSanitizedString( url );
- extra->hashValue = 0;
+ extra->_additionalDataFlags = _getAdditionalDataFlags(url);
+ extra->_sanitizedString = _getSanitizedString(url);
- url->extra = extra;
+ url->_extra = extra;
#if DEBUG_URL_MEMORY_USAGE
numExtraDataAllocated ++;
CF_INLINE void _setReserved ( struct __CFURL* url, void* reserved )
{
- if ( url )
- {
- // Don't allocate extra space if we're just going to be storing NULL
- if ( ! url->extra && reserved )
- _CFURLAllocateExtraDataspace( url );
-
- if ( url->extra )
- __CFAssignWithWriteBarrier((void **)&url->extra->_reserved, reserved);
- }
+ if ( url )
+ {
+ // Don't allocate extra space if we're just going to be storing NULL
+ if ( !url->_extra && reserved )
+ _CFURLAllocateExtraDataspace( url );
+
+ if ( url->_extra )
+ __CFAssignWithWriteBarrier((void **)&url->_extra->_reserved, reserved);
+ }
}
-CF_INLINE void _setSanitizedString ( struct __CFURL* url, CFMutableStringRef sanitizedString )
+CF_INLINE void _setSanitizedString( struct __CFURL* url, CFMutableStringRef sanitizedString )
{
- if ( url )
- {
- // Don't allocate extra space if we're just going to be storing NULL
- if ( ! url->extra && sanitizedString )
- _CFURLAllocateExtraDataspace( url );
-
- if ( url->extra )
- url->extra->_sanitizedString = sanitizedString;
- }
+ if ( url )
+ {
+ // Don't allocate extra space if we're just going to be storing NULL
+ if ( !url->_extra && sanitizedString ) {
+ _CFURLAllocateExtraDataspace( url );
+ }
+
+ if ( url->_extra ) {
+ if ( url->_extra->_sanitizedString ) {
+ CFRelease(url->_extra->_sanitizedString);
+ }
+ url->_extra->_sanitizedString = CFStringCreateCopy(CFGetAllocator(url), sanitizedString);
+
+ }
+ }
+}
+
+CF_INLINE void _setAdditionalDataFlags(struct __CFURL* url, UInt32 additionalDataFlags)
+{
+ if ( url )
+ {
+ // Don't allocate extra space if we're just going to be storing 0
+ if ( !url->_extra && (additionalDataFlags != 0) ) {
+ _CFURLAllocateExtraDataspace( url );
+ }
+
+ if ( url->_extra ) {
+ url->_extra->_additionalDataFlags = additionalDataFlags;
+ }
+ }
}
-static void _setResourceInfo ( struct __CFURL* url, void* resourceInfo )
+CF_INLINE void _setResourceInfo ( struct __CFURL* url, void* resourceInfo )
{
// Must be atomic
// Never a GC object
}
}
-static void _convertToURLRepresentation(struct __CFURL *url);
-static CFURLRef _CFURLCopyAbsoluteFileURL(CFURLRef relativeURL);
+CF_INLINE UInt32 _getSchemeTypeFromFlags(UInt32 flags)
+{
+ return ( (flags & SCHEME_TYPE_MASK) >> SCHEME_SHIFT );
+}
+
+CF_INLINE void _setSchemeTypeInFlags(UInt32 *flags, UInt32 schemeType)
+{
+ CFAssert2((schemeType >= kHasUncommonScheme) && (schemeType < kMaxScheme), __kCFLogAssertion, "%s(): Received bad schemeType %d", __PRETTY_FUNCTION__, 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);
CF_INLINE void _parseComponentsOfURL(CFURLRef url) {
- _parseComponents(CFGetAllocator(url), url->_string, url->_base, &(((struct __CFURL *)url)->_flags), &(((struct __CFURL *)url)->ranges));
-}
-
-static Boolean _createOldUTF8StyleURLs = false;
-
-CF_INLINE Boolean createOldUTF8StyleURLs(void) {
- return (_createOldUTF8StyleURLs);
-}
-
-// Our backdoor in case removing the UTF8 constraint for URLs creates unexpected problems. See radar 2902530 -- REW
-CF_EXPORT
-void _CFURLCreateOnlyUTF8CompatibleURLs(Boolean createUTF8URLs) {
- _createOldUTF8StyleURLs = createUTF8URLs;
+ _parseComponents(CFGetAllocator(url), url->_string, url->_base, &(((struct __CFURL *)url)->_flags), &(((struct __CFURL *)url)->_ranges));
}
enum {
HEXDIGIT = 16
};
-static const unsigned char sURLValidCharacters[] = {
- /* ' ' 32 */ 0,
- /* '!' 33 */ VALID | UNRESERVED | 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 ,
- /* '+' 43 */ VALID | SCHEME | PATHVALID ,
- /* ',' 44 */ VALID | PATHVALID ,
- /* '-' 45 */ VALID | UNRESERVED | SCHEME | PATHVALID ,
- /* '.' 46 */ VALID | UNRESERVED | 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 ,
- /* ':' 58 */ VALID ,
- /* ';' 59 */ VALID ,
- /* '<' 60 */ 0,
- /* '=' 61 */ VALID | PATHVALID ,
- /* '>' 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 ,
- /* '[' 91 */ 0,
- /* '\' 92 */ 0,
- /* ']' 93 */ 0,
- /* '^' 94 */ 0,
- /* '_' 95 */ VALID | UNRESERVED | 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 ,
- /* '{' 123 */ 0,
- /* '|' 124 */ 0,
- /* '}' 125 */ 0,
- /* '~' 126 */ VALID | UNRESERVED | PATHVALID ,
- /* '' 127 */ 0
+static const unsigned char sURLValidCharacters[128] = {
+ /* 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 */ VALID | UNRESERVED | 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 ,
+ /* '+' 43 */ VALID | SCHEME | PATHVALID ,
+ /* ',' 44 */ VALID | PATHVALID ,
+ /* '-' 45 */ VALID | UNRESERVED | SCHEME | PATHVALID ,
+ /* '.' 46 */ VALID | UNRESERVED | 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 ,
+ /* ':' 58 */ VALID ,
+ /* ';' 59 */ VALID ,
+ /* '<' 60 */ 0,
+ /* '=' 61 */ VALID | PATHVALID ,
+ /* '>' 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 ,
+ /* '[' 91 */ 0,
+ /* '\' 92 */ 0,
+ /* ']' 93 */ 0,
+ /* '^' 94 */ 0,
+ /* '_' 95 */ VALID | UNRESERVED | 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 ,
+ /* '{' 123 */ 0,
+ /* '|' 124 */ 0,
+ /* '}' 125 */ 0,
+ /* '~' 126 */ VALID | UNRESERVED | PATHVALID ,
+ /* del 127 */ 0,
};
CF_INLINE Boolean isURLLegalCharacter(UniChar ch) {
- return ( ( 32 <= ch ) && ( ch <= 127 ) ) ? ( sURLValidCharacters[ ch - 32 ] & VALID ) : false;
+ return (ch <= 127) ? (sURLValidCharacters[ch] & VALID) : false;
}
CF_INLINE Boolean scheme_valid(UniChar ch) {
- return ( ( 32 <= ch ) && ( ch <= 127 ) ) ? ( sURLValidCharacters[ ch - 32 ] & SCHEME ) : false;
+ return (ch <= 127) ? (sURLValidCharacters[ch] & SCHEME) : false;
}
// "Unreserved" as defined by RFC 2396
CF_INLINE Boolean isUnreservedCharacter(UniChar ch) {
- return ( ( 32 <= ch ) && ( ch <= 127 ) ) ? ( sURLValidCharacters[ ch - 32 ] & UNRESERVED ) : false;
+ return (ch <= 127) ? (sURLValidCharacters[ch] & UNRESERVED) : false;
}
CF_INLINE Boolean isPathLegalCharacter(UniChar ch) {
- return ( ( 32 <= ch ) && ( ch <= 127 ) ) ? ( sURLValidCharacters[ ch - 32 ] & PATHVALID ) : false;
+ return (ch <= 127) ? (sURLValidCharacters[ch] & PATHVALID) : false;
}
CF_INLINE Boolean isHexDigit(UniChar ch) {
- return ( ( 32 <= ch ) && ( ch <= 127 ) ) ? ( sURLValidCharacters[ ch - 32 ] & HEXDIGIT ) : false;
+ return (ch <= 127) ? (sURLValidCharacters[ch] & HEXDIGIT) : false;
}
// Returns false if ch1 or ch2 isn't properly formatted
return ((url->_flags & ORIGINAL_AND_URL_STRINGS_MATCH) != 0) || (_getSanitizedString(url) != NULL);
}
-typedef CFStringRef (*StringTransformation)(CFAllocatorRef, CFStringRef, CFIndex);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-static CFArrayRef copyStringArrayWithTransformation(CFArrayRef array, StringTransformation transformation) {
- CFAllocatorRef alloc = CFGetAllocator(array);
- CFMutableArrayRef mArray = NULL;
- CFIndex i, c = CFArrayGetCount(array);
- for (i = 0; i < c; i ++) {
- CFStringRef origComp = (CFStringRef)CFArrayGetValueAtIndex(array, i);
- CFStringRef unescapedComp = transformation(alloc, origComp, i);
- if (!unescapedComp) {
- break;
+/*
+ CreateStringFromFileSystemRepresentationByAddingPercentEscapes creates a CFString
+ for the path-absolute form of a URI path component 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 CreateStringFromFileSystemRepresentationByAddingPercentEscapes(CFAllocatorRef alloc, const UInt8 *bytes, CFIndex numBytes, Boolean windowsPath)
+{
+ static const UInt8 hexchars[] = "0123456789ABCDEF";
+ STACK_BUFFER_DECL(UInt8, stackBuf, PATH_MAX * 3); // worst case is every byte needs to be percent-escaped
+ UInt8 *bufStartPtr;
+ UInt8 *bufBytePtr;
+ const UInt8 *bytePtr = bytes;
+ CFIndex idx;
+ CFStringRef result;
+
+ // 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);
+ }
+
+ 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
+ *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;
+ }
+ ++bytePtr;
}
- if (unescapedComp != origComp) {
- if (!mArray) {
- mArray = CFArrayCreateMutableCopy(alloc, c, array);
+
+ // did we convert numBytes?
+ if ( idx == numBytes ) {
+ // create the result
+ result = CFStringCreateWithBytes(alloc, bufStartPtr, (CFIndex)(bufBytePtr-bufStartPtr), kCFStringEncodingUTF8, FALSE);
+ }
+ else {
+ // 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 ) {
+ // do nothing
+ }
+ if ( idx == numBytes ) {
+ // create the result
+ result = CFStringCreateWithBytes(alloc, bufStartPtr, (CFIndex)(bufBytePtr-bufStartPtr), kCFStringEncodingUTF8, FALSE);
+ }
+ else {
+ // the remaining bytes were not all nul
+ result = NULL;
}
- CFArraySetValueAtIndex(mArray, i, unescapedComp);
}
- CFRelease(unescapedComp);
+
+ // free the buffer if we malloc'd it
+ if ( bufStartPtr != &stackBuf[0] ) {
+ free(bufStartPtr);
+ }
}
- if (i != c) {
- if (mArray) CFRelease(mArray);
- return NULL;
- } else if (mArray) {
- return mArray;
- } else {
- CFRetain(array);
- return array;
+ else {
+ result = NULL;
}
+ return ( result );
}
-#endif
// Returns NULL if str cannot be converted for whatever reason, str if str contains no characters in need of escaping, or a newly-created string with the appropriate % escape codes in place. Caller must always release the returned string.
CF_INLINE CFStringRef _replacePathIllegalCharacters(CFStringRef str, CFAllocatorRef alloc, Boolean preserveSlashes) {
- if (preserveSlashes) {
- return CFURLCreateStringByAddingPercentEscapes(alloc, str, NULL, CFSTR(";?"), kCFStringEncodingUTF8);
- } else {
- return CFURLCreateStringByAddingPercentEscapes(alloc, str, NULL, CFSTR(";?/"), kCFStringEncodingUTF8);
+ 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);
}
+ return result;
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-static CFStringRef escapePathComponent(CFAllocatorRef alloc, CFStringRef origComponent, CFIndex componentIndex) {
- return CFURLCreateStringByAddingPercentEscapes(alloc, origComponent, NULL, CFSTR(";?/"), kCFStringEncodingUTF8);
-}
-#endif
-
// 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];
strings[1] = legalURLCharactersToBeEscaped;
return _addPercentEscapesToString(allocator, originalString, _shouldPercentReplaceChar, NULL, encoding, strings);
}
-
-
-#if 0
-static Boolean __CFURLCompare(CFTypeRef cf1, CFTypeRef cf2) {
- CFURLRef url1 = (CFURLRef)cf1;
- CFURLRef url2 = (CFURLRef)cf2;
- UInt32 pathType1, pathType2;
-
- __CFGenericValidateType(cf1, CFURLGetTypeID());
- __CFGenericValidateType(cf2, CFURLGetTypeID());
-
- if (url1 == url2) return kCFCompareEqualTo;
-
- if ( url1->_base ) {
- if (! url2->_base) return kCFCompareEqualTo;
- if (!CFEqual( url1->_base, url2->_base )) return false;
- } else if ( url2->_base) {
- return false;
- }
-
- pathType1 = URL_PATH_TYPE(url1);
- pathType2 = URL_PATH_TYPE(url2);
- if (pathType1 == pathType2) {
- if (pathType1 != FULL_URL_REPRESENTATION) {
- return CFEqual(url1->_string, url2->_string);
- } else {
- // Do not compare the original strings; compare the sanatized strings.
- return CFEqual(CFURLGetString(url1), CFURLGetString(url2));
- }
- } else {
- // Try hard to avoid the expensive conversion from a file system representation to the canonical form
- CFStringRef scheme1 = CFURLCopyScheme(url1);
- CFStringRef scheme2 = CFURLCopyScheme(url2);
- Boolean eq;
- if (scheme1 && scheme2) {
- eq = CFEqual(scheme1, scheme2);
- CFRelease(scheme1);
- CFRelease(scheme2);
- } else if (!scheme1 && !scheme2) {
- eq = TRUE;
- } else {
- eq = FALSE;
- if (scheme1) CFRelease(scheme1);
- else CFRelease(scheme2);
- }
- if (!eq) return false;
-
- if (pathType1 == FULL_URL_REPRESENTATION) {
- if (!(url1->_flags & IS_PARSED)) {
- _parseComponentsOfURL(url1);
- }
- if (url1->_flags & (HAS_USER | HAS_PORT | HAS_PASSWORD | HAS_QUERY | HAS_PARAMETERS | HAS_FRAGMENT )) {
- return false;
- }
- }
-
- if (pathType2 == FULL_URL_REPRESENTATION) {
- if (!(url2->_flags & IS_PARSED)) {
- _parseComponentsOfURL(url2);
- }
- if (url2->_flags & (HAS_USER | HAS_PORT | HAS_PASSWORD | HAS_QUERY | HAS_PARAMETERS | HAS_FRAGMENT )) {
- return false;
- }
- }
-
- // No help for it; we now must convert to the canonical representation and compare.
- return CFEqual(CFURLGetString(url1), CFURLGetString(url2));
- }
-}
-#endif
static Boolean __CFURLEqual(CFTypeRef cf1, CFTypeRef cf2) {
+ Boolean result;
CFURLRef url1 = (CFURLRef)cf1;
CFURLRef url2 = (CFURLRef)cf2;
- UInt32 pathType1, pathType2;
__CFGenericValidateType(cf1, CFURLGetTypeID());
__CFGenericValidateType(cf2, CFURLGetTypeID());
- if (url1 == url2) return true;
- if ((url1->_flags & IS_PARSED) && (url2->_flags & IS_PARSED) && (url1->_flags & IS_DIRECTORY) != (url2->_flags & IS_DIRECTORY)) return false;
- if ( url1->_base ) {
- if (! url2->_base) return false;
- if (!CFEqual( url1->_base, url2->_base )) return false;
- } else if ( url2->_base) {
- return false;
+ if ( url1 == url2 ) {
+ result = true;
}
-
- pathType1 = URL_PATH_TYPE(url1);
- pathType2 = URL_PATH_TYPE(url2);
- if (pathType1 == pathType2) {
- if (pathType1 != FULL_URL_REPRESENTATION) {
- return CFEqual(url1->_string, url2->_string);
- } else {
- // Do not compare the original strings; compare the sanatized strings.
- return CFEqual(CFURLGetString(url1), CFURLGetString(url2));
- }
- } else {
- // Try hard to avoid the expensive conversion from a file system representation to the canonical form
- CFStringRef scheme1 = CFURLCopyScheme(url1);
- CFStringRef scheme2 = CFURLCopyScheme(url2);
- Boolean eq;
- if (scheme1 && scheme2) {
- eq = CFEqual(scheme1, scheme2);
- CFRelease(scheme1);
- CFRelease(scheme2);
- } else if (!scheme1 && !scheme2) {
- eq = TRUE;
- } else {
- eq = FALSE;
- if (scheme1) CFRelease(scheme1);
- else CFRelease(scheme2);
- }
- if (!eq) return false;
-
- if (pathType1 == FULL_URL_REPRESENTATION) {
- if (!(url1->_flags & IS_PARSED)) {
- _parseComponentsOfURL(url1);
- }
- if (url1->_flags & (HAS_USER | HAS_PORT | HAS_PASSWORD | HAS_QUERY | HAS_PARAMETERS | HAS_FRAGMENT )) {
- return false;
- }
+ else {
+ if ( (url1->_flags & EQUAL_FLAGS_MASK) != (url2->_flags & EQUAL_FLAGS_MASK) ) {
+ result = false;
}
-
- if (pathType2 == FULL_URL_REPRESENTATION) {
- if (!(url2->_flags & IS_PARSED)) {
- _parseComponentsOfURL(url2);
+ else {
+ if ( (url1->_base && !url2->_base) ||
+ (!url1->_base && url2->_base) ||
+ (url1->_base && url2->_base && !CFEqual(url1->_base, url2->_base)) ) {
+ result = false;
}
- if (url2->_flags & (HAS_USER | HAS_PORT | HAS_PASSWORD | HAS_QUERY | HAS_PARAMETERS | HAS_FRAGMENT )) {
- return false;
+ else {
+ // no base urls, so compare the URL strings
+ // Do not compare the original strings; compare the sanatized strings.
+ result = CFEqual(CFURLGetString(url1), CFURLGetString(url2));
}
}
-
- // No help for it; we now must convert to the canonical representation and compare.
- return CFEqual(CFURLGetString(url1), CFURLGetString(url2));
}
+ return ( result ) ;
}
-static CFHashCode __CFURLHash(CFTypeRef cf) {
- /* This is tricky, because we do not want the hash value to change as a file system URL is changed to its canonical representation, nor do we wish to force the conversion to the canonical representation. We choose instead to take the last path component (or "/" in the unlikely case that the path is empty), then hash on that. */
- struct __CFURL* url = (struct __CFURL*)cf;
- CFHashCode result = 0;
+static CFHashCode __CFURLHash(CFTypeRef cf)
+{
+ CFHashCode result;
- if ( url )
- {
- // Allocate our extra space if it isn't already allocated
- if ( url && ! url->extra )
- _CFURLAllocateExtraDataspace( url );
-
- if ( url->extra ) {
- result = url->extra->hashValue;
-
- if ( ! result ) {
- if (CFURLCanBeDecomposed(url)) {
- CFStringRef lastComp = CFURLCopyLastPathComponent(url);
- CFStringRef hostNameRef = CFURLCopyHostName(url );
-
- result = 0;
-
- if (lastComp) {
- result = CFHash(lastComp);
- CFRelease(lastComp);
- }
-
- if ( hostNameRef ) {
- result ^= CFHash( hostNameRef );
- CFRelease( hostNameRef );
- }
- } else {
- result = CFHash(CFURLGetString(url));
- }
-
- if ( ! result ) // never store a 0 value for the hashed value
- result = 1;
-
- url->extra->hashValue = result;
- }
- }
+ if ( cf ) {
+ // use the CFHashCode of the URL
+ result = CFHash(CFURLGetString((CFURLRef)cf));
+ }
+ else {
+ // no object, no hashcode
+ result = 0;
}
- return result;
+ return ( result );
}
static CFStringRef __CFURLCopyFormattingDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
CFURLRef url = (CFURLRef)cf;
__CFGenericValidateType(cf, CFURLGetTypeID());
if (! url->_base) {
-#if DEPLOYMENT_TARGET_MACOSX
- {
- CFRetain(url->_string);
- return url->_string;
- }
-#else
CFRetain(url->_string);
return url->_string;
-#endif
} else {
// Do not dereference url->_base; it may be an ObjC object
return CFStringCreateWithFormat(CFGetAllocator(url), NULL, CFSTR("%@ -- %@"), url->_string, url->_base);
CFAllocatorRef alloc = CFGetAllocator(url);
if ( url->_base) {
CFStringRef baseString = CFCopyDescription(url->_base);
- result = CFStringCreateWithFormat(alloc, NULL, CFSTR("<CFURL %p [%p]>{type = %d, string = %@, encoding = %d\n\tbase = %@}"), cf, alloc, URL_PATH_TYPE(url), url->_string, url->_encoding, baseString);
+ result = CFStringCreateWithFormat(alloc, NULL, CFSTR("<CFURL %p [%p]>{string = %@, encoding = %d\n\tbase = %@}"), cf, alloc, url->_string, url->_encoding, baseString);
CFRelease(baseString);
} else {
- result = CFStringCreateWithFormat(alloc, NULL, CFSTR("<CFURL %p [%p]>{type = %d, string = %@, encoding = %d, base = (null)}"), cf, alloc, URL_PATH_TYPE(url), url->_string, url->_encoding);
+ result = CFStringCreateWithFormat(alloc, NULL, CFSTR("<CFURL %p [%p]>{string = %@, encoding = %d, base = (null)}"), cf, alloc, url->_string, url->_encoding);
}
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 converted; %d destroyed. %d urls had 'extra' data allocated, %d had base urls, %d were not UTF8 encoded\n"), numURLs, numDealloced, numFileURLsCreated, numFileURLsConverted, numFileURLsDealloced, numExtraDataAllocated, numURLsWithBaseURL, numNonUTF8EncodedURLs );
+ 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);
- // if (URLAllocator) CFCountingAllocatorPrintPointers(URLAllocator);
}
#endif
alloc = CFGetAllocator(url);
#if DEBUG_URL_MEMORY_USAGE
numDealloced ++;
- if (URL_PATH_TYPE(url) != FULL_URL_REPRESENTATION) {
- numFileURLsDealloced ++;
- }
#endif
if (url->_string) CFRelease(url->_string); // GC: 3879914
if (url->_base) CFRelease(url->_base);
- if (url->ranges) CFAllocatorDeallocate(alloc, url->ranges);
- if (_getSanitizedString(url)) CFRelease(_getSanitizedString(url));
- if ( url->extra != NULL ) CFAllocatorDeallocate( alloc, url->extra );
+ if (url->_ranges) CFAllocatorDeallocate(alloc, url->_ranges);
+ CFStringRef sanitizedString = _getSanitizedString(url);
+ if (sanitizedString) CFRelease(sanitizedString);
+ if ( url->_extra != NULL ) CFAllocatorDeallocate( alloc, url->_extra );
if (_getResourceInfo(url)) CFRelease(_getResourceInfo(url));
}
static CFTypeID __kCFURLTypeID = _kCFRuntimeNotATypeID;
static const CFRuntimeClass __CFURLClass = {
- 0,
- "CFURL",
- NULL, // init
- NULL, // copy
- __CFURLDeallocate,
- __CFURLEqual,
- __CFURLHash,
- __CFURLCopyFormattingDescription,
- __CFURLCopyDescription
+ 0, // version
+ "CFURL", // className
+ NULL, // init
+ NULL, // copy
+ __CFURLDeallocate, // finalize
+ __CFURLEqual, // equal
+ __CFURLHash, // hash
+ __CFURLCopyFormattingDescription, // copyFormattingDesc
+ __CFURLCopyDescription, // copyDebugDesc
+ NULL, // reclaim
+ 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(kCFURLHTTPScheme, "http")
+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(kCFURLHTTPScheme, "http")
+CONST_STRING_DECL(kCFURLFTPScheme, "ftp")
CONST_STRING_DECL(kCFURLLocalhost, "localhost")
#endif
__private_extern__ void __CFURLInitialize(void) {
/* Toll-free bridging support; get the true CFURL from an NSURL */
CF_INLINE CFURLRef _CFURLFromNSURL(CFURLRef url) {
- CF_OBJC_FUNCDISPATCH0(__kCFURLTypeID, CFURLRef, url, "_cfurl");
+ CF_OBJC_FUNCDISPATCHV(__kCFURLTypeID, CFURLRef, (NSURL *)url, _cfurl);
return url;
}
fprintf(stdout, "ObjC bridged object}\n");
return;
}
- fprintf(stdout, "\n\tPath type: ");
- switch (URL_PATH_TYPE(url)) {
- case kCFURLPOSIXPathStyle:
- fprintf(stdout, "POSIX");
- break;
- case kCFURLHFSPathStyle:
- fprintf(stdout, "HFS");
- break;
- case kCFURLWindowsPathStyle:
- fprintf(stdout, "NTFS");
- break;
- case FULL_URL_REPRESENTATION:
- fprintf(stdout, "Native URL");
- break;
- default:
- fprintf(stdout, "UNRECOGNIZED PATH TYPE %d", (char)URL_PATH_TYPE(url));
- }
fprintf(stdout, "\n\tRelative string: ");
CFShow(url->_string);
fprintf(stdout, "\tBase URL: ");
/***************************************************/
/* URL creation and String/Data creation from URLS */
/***************************************************/
-static void constructBuffers(CFAllocatorRef alloc, CFStringRef string, const char **cstring, const UniChar **ustring, Boolean *useCString, Boolean *freeCharacters) {
+static void constructBuffers(CFAllocatorRef alloc, CFStringRef string, Boolean useEightBitStringEncoding, UInt8 *inBuffer, CFIndex inBufferSize, const char **cstring, const UniChar **ustring, Boolean *useCString, Boolean *freeCharacters) {
CFIndex neededLength;
CFIndex length;
CFRange rg;
- *cstring = CFStringGetCStringPtr(string, kCFStringEncodingISOLatin1);
+ *cstring = CFStringGetCStringPtr(string, (useEightBitStringEncoding ? __CFStringGetEightBitStringEncoding() : kCFStringEncodingISOLatin1));
if (*cstring) {
*ustring = NULL;
*useCString = true;
return;
}
- *freeCharacters = true;
length = CFStringGetLength(string);
rg = CFRangeMake(0, length);
CFStringGetBytes(string, rg, kCFStringEncodingISOLatin1, 0, false, NULL, INT_MAX, &neededLength);
if (neededLength == length) {
- char *buf = (char *)CFAllocatorAllocate(alloc, length, 0);
+ char *buf;
+ if ( (inBuffer != NULL) && (length <= inBufferSize) ) {
+ buf = (char *)inBuffer;
+ *freeCharacters = false;
+ }
+ else {
+ buf = (char *)CFAllocatorAllocate(alloc, length, 0);
+ *freeCharacters = true;
+ }
CFStringGetBytes(string, rg, kCFStringEncodingISOLatin1, 0, false, (uint8_t *)buf, length, NULL);
*cstring = buf;
*useCString = true;
} else {
- UniChar *buf = (UniChar *)CFAllocatorAllocate(alloc, length * sizeof(UniChar), 0);
+ UniChar *buf;
+ if ( (inBuffer != NULL) && ((length * sizeof(UniChar)) <= inBufferSize) ) {
+ buf = (UniChar *)inBuffer;
+ *freeCharacters = false;
+ }
+ else {
+ buf = (UniChar *)CFAllocatorAllocate(alloc, length * sizeof(UniChar), 0);
+ *freeCharacters = true;
+ }
CFStringGetCharacters(string, rg, buf);
- *useCString = false;
*ustring = buf;
+ *useCString = false;
}
}
CFIndex idx, base_idx = 0;
CFIndex string_length;
- UInt32 flags = (IS_PARSED | *theFlags);
+ UInt32 flags = *theFlags;
+ Boolean useEightBitStringEncoding = (flags & USES_EIGHTBITSTRINGENCODING) != 0;
Boolean useCString, freeCharacters, isCompliant;
uint8_t numRanges = 0;
const char *cstring = NULL;
const UniChar *ustring = NULL;
+ CFIndex stackBufferSize = 4096;
+ STACK_BUFFER_DECL(UInt8, stackBuffer, stackBufferSize);
string_length = CFStringGetLength(string);
- constructBuffers(alloc, string, &cstring, &ustring, &useCString, &freeCharacters);
+ constructBuffers(alloc, string, useEightBitStringEncoding, stackBuffer, stackBufferSize, &cstring, &ustring, &useCString, &freeCharacters);
// Algorithm is as described in RFC 1808
// 1: parse the fragment; remainder after left-most "#" is fragment
ranges[0].length = idx;
numRanges ++;
base_idx = idx + 1;
- // optimization for http urls
- if (idx == 4 && STRING_CHAR(0) == 'h' && STRING_CHAR(1) == 't' && STRING_CHAR(2) == 't' && STRING_CHAR(3) == 'p') {
- flags |= HAS_HTTP_SCHEME;
+ // 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 file urls
- if (idx == 4 && STRING_CHAR(0) == 'f' && STRING_CHAR(1) == 'i' && STRING_CHAR(2) == 'l' && STRING_CHAR(3) == 'e') {
- flags |= HAS_FILE_SCHEME;
+ // 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;
}
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#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) {
if (!sawPercent) {
flags |= POSIX_AND_URL_PATHS_MATCH;
}
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
ch = STRING_CHAR(pathRg.location + pathRg.length - 1);
} else {
shouldEscape = true;
}
- if (!shouldEscape) continue;
-
- sawIllegalChar = true;
- if (componentFlag && flags) {
- *flags |= (componentFlag << BIT_SHIFT_FROM_COMPONENT_TO_DIFFERS_FLAG);
- }
- 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);
+ 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
}
- *mark = idx + 1;
- _appendPercentEscapesForCharacter(ch, encoding, *escapedString); // This can never fail because anURL->_string was constructed from the encoding passed in
}
return sawIllegalChar;
}
const UniChar *ustring = NULL;
CFIndex base; // where to scan from
CFIndex mark; // first character not-yet copied to sanitized string
- if (!(url->_flags & IS_PARSED)) {
- _parseComponentsOfURL(url);
- }
- constructBuffers(alloc, url->_string, &cstring, &ustring, &useCString, &freeCharacters);
+ CFIndex stackBufferSize = 4096;
+ 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);
if (!(url->_flags & IS_DECOMPOSABLE)) {
// Impossible to have a problem character in the scheme
- CFMutableStringRef sanitizedString = NULL;
- base = _rangeForComponent(url->_flags, url->ranges, HAS_SCHEME).length + 1;
+ base = _rangeForComponent(url->_flags, url->_ranges, HAS_SCHEME).length + 1;
mark = 0;
- if (!scanCharacters(alloc, & sanitizedString, &(((struct __CFURL *)url)->_flags), cstring, ustring, useCString, base, string_length, &mark, 0, url->_encoding)) {
+ if (!scanCharacters(alloc, &sanitizedString, &additionalDataFlags, cstring, ustring, useCString, base, string_length, &mark, 0, url->_encoding)) {
((struct __CFURL *)url)->_flags |= ORIGINAL_AND_URL_STRINGS_MATCH;
}
if ( sanitizedString ) {
- _setSanitizedString( (struct __CFURL*) url, sanitizedString );
+ _setAdditionalDataFlags((struct __CFURL*)url, additionalDataFlags);
}
} else {
// Go component by component
CFIndex currentComponent = HAS_USER;
- CFMutableStringRef sanitizedString = NULL;
mark = 0;
while (currentComponent < (HAS_FRAGMENT << 1)) {
- CFRange componentRange = _rangeForComponent(url->_flags, url->ranges, currentComponent);
+ CFRange componentRange = _rangeForComponent(url->_flags, url->_ranges, currentComponent);
if (componentRange.location != kCFNotFound) {
- scanCharacters(alloc, & sanitizedString, &(((struct __CFURL *)url)->_flags), 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;
}
if (sanitizedString) {
- _setSanitizedString((struct __CFURL *)url, sanitizedString);
+ _setAdditionalDataFlags((struct __CFURL*)url, additionalDataFlags);
} else {
((struct __CFURL *)url)->_flags |= ORIGINAL_AND_URL_STRINGS_MATCH;
}
}
- if (_getSanitizedString(url) && mark != string_length) {
+ if (sanitizedString && mark != string_length) {
if (useCString) {
CFStringRef tempString = CFStringCreateWithBytes(alloc, (uint8_t *)&(cstring[mark]), string_length - mark, kCFStringEncodingISOLatin1, false);
- CFStringAppend(_getSanitizedString(url), tempString);
+ CFStringAppend(sanitizedString, tempString);
CFRelease(tempString);
} else {
- CFStringAppendCharacters(_getSanitizedString(url), &(ustring[mark]), string_length - mark);
+ CFStringAppendCharacters(sanitizedString, &(ustring[mark]), string_length - mark);
}
}
+ if ( sanitizedString ) {
+ _setSanitizedString((struct __CFURL*) url, sanitizedString);
+ CFRelease(sanitizedString);
+ }
if (freeCharacters) {
CFAllocatorDeallocate(alloc, useCString ? (void *)cstring : (void *)ustring);
}
const UniChar *ustring = NULL;
CFIndex mark = 0; // first character not-yet copied to sanitized string
CFMutableStringRef result = NULL;
+ CFIndex stackBufferSize = 1024;
+ STACK_BUFFER_DECL(UInt8, stackBuffer, stackBufferSize);
- constructBuffers(alloc, comp, &cstring, &ustring, &useCString, &freeCharacters);
+ constructBuffers(alloc, comp, false, 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) {
struct __CFURL *url;
#if DEBUG_URL_MEMORY_USAGE
numURLs ++;
- // if (!URLAllocator) {
- // URLAllocator = CFCountingAllocatorCreate(NULL);
- // }
- allocator = URLAllocator;
#endif
url = (struct __CFURL *)_CFRuntimeCreateInstance(allocator, __kCFURLTypeID, sizeof(struct __CFURL) - sizeof(CFRuntimeBase), NULL);
if (url) {
url->_flags = 0;
- if (createOldUTF8StyleURLs()) {
- url->_flags |= IS_OLD_UTF8_STYLE;
- }
url->_encoding = kCFStringEncodingUTF8;
url->_string = NULL;
url->_base = NULL;
- url->ranges = NULL;
- url->extra = NULL;
+ url->_ranges = NULL;
+ url->_extra = NULL;
url->_resourceInfo = NULL;
- // url->_reserved = NULL;
- // url->_sanatizedString = NULL;
}
return url;
}
// It is the caller's responsibility to guarantee that if URLString is absolute, base is NULL. This is necessary to avoid duplicate processing for file system URLs, which had to decide whether to compute the cwd for the base; we don't want to duplicate that work. 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) || ASSERT_CHECK_PATHSTYLE(fsType), __kCFLogAssertion, "%s(): Received bad fsType %d", __PRETTY_FUNCTION__, fsType);
+ CFAssert2((fsType == FULL_URL_REPRESENTATION) || (fsType == kCFURLPOSIXPathStyle) || (fsType == kCFURLWindowsPathStyle) || (fsType == kCFURLHFSPathStyle), __kCFLogAssertion, "%s(): Received bad fsType %d", __PRETTY_FUNCTION__, fsType);
// Coming in, the url has its allocator flag properly set, and its base initialized, and nothing else.
- url->_string = (CFStringRef)CFStringCreateCopy(CFGetAllocator(url), URLString);
- url->_flags |= (fsType << 16);
-
+ url->_string = CFStringCreateCopy(CFGetAllocator(url), URLString);
url->_base = base ? CFURLCopyAbsoluteURL(base) : NULL;
#if DEBUG_URL_MEMORY_USAGE
- if (fsType != FULL_URL_REPRESENTATION) {
+ if ( (fsType == kCFURLPOSIXPathStyle) || (fsType == kCFURLHFSPathStyle) || (fsType == kCFURLWindowsPathStyle) ) {
numFileURLsCreated ++;
}
- if ( url->_base )
+ if ( url->_base ) {
numURLsWithBaseURL ++;
+ }
#endif
- {
- if (URL_PATH_TYPE(url) != FULL_URL_REPRESENTATION) {
- _convertToURLRepresentation((struct __CFURL *)url);
- }
- if (!(url->_flags & IS_PARSED)) {
- _parseComponentsOfURL(url);
- }
+ if (fsType != FULL_URL_REPRESENTATION) {
+ // _convertToURLRepresentation parses the URL
+ _convertToURLRepresentation((struct __CFURL *)url, fsType);
+ }
+ else {
+ _parseComponentsOfURL(url);
}
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#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) == '/') {
CFRelease(cwdURL);
}
}
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
// Exported for Foundation's use
Boolean encodingsMatch;
} ;
-static Boolean _shouldEscapeForEncodingConversion(UniChar ch, void *context) {
- struct __CFURLEncodingTranslationParameters *info = (struct __CFURLEncodingTranslationParameters *)context;
- if (info->escapeHighBit && ch > 0x7F) {
- return true;
- } else if (ch == '%' && info->escapePercents) {
- return true;
- } else if (info->addlChars) {
- const UniChar *escChar = info->addlChars;
- int i;
- for (i = 0; i < info->count; escChar ++, i ++) {
- if (*escChar == ch) {
- return true;
- }
- }
- }
- return false;
-}
-
-static CFIndex _convertEscapeSequence(CFIndex percentIndex, CFStringRef urlString, CFStringRef *newString, void *context) {
- struct __CFURLEncodingTranslationParameters *info = (struct __CFURLEncodingTranslationParameters *)context;
- CFMutableDataRef newData;
- Boolean sawNonASCIICharacter = false;
- CFIndex i = percentIndex;
- CFIndex length;
- *newString = NULL;
- if (info->encodingsMatch) return percentIndex + 3; // +3 because we want the two characters of the percent encoding to not be copied verbatim, as well
- newData = CFDataCreateMutable(CFGetAllocator(urlString), 0);
- length = CFStringGetLength(urlString);
-
- while (i < length && CFStringGetCharacterAtIndex(urlString, i) == '%') {
- uint8_t byte;
- if (i+2 >= length || !_translateBytes(CFStringGetCharacterAtIndex(urlString, i+1), CFStringGetCharacterAtIndex(urlString, i+2), &byte)) {
- CFRelease(newData);
- return -1;
- }
- if (byte > 0x7f) sawNonASCIICharacter = true;
- CFDataAppendBytes(newData, &byte, 1);
- i += 3;
- }
- if (!sawNonASCIICharacter && info->agreesOverASCII) {
- CFRelease(newData);
- return i;
- } else {
- CFStringRef tmp = CFStringCreateWithBytes(CFGetAllocator(urlString), CFDataGetBytePtr(newData), CFDataGetLength(newData), info->fromEnc, false);
- CFIndex tmpIndex, tmpLen;
- if (!tmp) {
- CFRelease(newData);
- return -1;
- }
- tmpLen = CFStringGetLength(tmp);
- *newString = CFStringCreateMutable(CFGetAllocator(urlString), 0);
- for (tmpIndex = 0; tmpIndex < tmpLen; tmpIndex ++) {
- if (!_appendPercentEscapesForCharacter(CFStringGetCharacterAtIndex(tmp, tmpIndex), info->toEnc, (CFMutableStringRef)(*newString))) {
- break;
- }
- }
- CFRelease(tmp);
- CFRelease(newData);
- if (tmpIndex < tmpLen) {
- CFRelease(*newString);
- *newString = NULL;
- return -1;
- } else {
- return i;
- }
- }
-}
-
-/* Returned string is retained for the caller; if escapePercents is true, then we do not look for any %-escape encodings in urlString */
-static CFStringRef _convertPercentEscapes(CFStringRef urlString, CFStringEncoding fromEncoding, CFStringEncoding toEncoding, Boolean escapeAllHighBitCharacters, Boolean escapePercents, const UniChar *addlCharsToEscape, int numAddlChars) {
- struct __CFURLEncodingTranslationParameters context;
- context.fromEnc = fromEncoding;
- context.toEnc = toEncoding;
- context.addlChars = addlCharsToEscape;
- context.count = numAddlChars;
- context.escapeHighBit = escapeAllHighBitCharacters;
- context.escapePercents = escapePercents;
- context.agreesOverASCII = (__CFStringEncodingIsSupersetOfASCII(toEncoding) && __CFStringEncodingIsSupersetOfASCII(fromEncoding)) ? true : false;
- context.encodingsMatch = (fromEncoding == toEncoding) ? true : false;
- return _addPercentEscapesToString(CFGetAllocator(urlString), urlString, _shouldEscapeForEncodingConversion, _convertEscapeSequence, toEncoding, &context);
-}
-
// 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 = CFStringCreateWithBytes(allocator, URLBytes, length, encoding, false);
+ 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;
}
-#if DEPLOYMENT_TARGET_MACOSX
- if ( !baseURL && *URLBytes == '/' ) {
- CFLog(kCFLogLevelWarning, CFSTR("CFURLCreateWithBytes was passed these invalid URLBytes: '%@' (a file system path instead of an URL string). The URL created will not work with most file URL functions. CFURLCreateFromFileSystemRepresentation should be used instead."), urlString);
- }
-#endif
- if (createOldUTF8StyleURLs()) {
- if (encoding != kCFStringEncodingUTF8) {
- CFStringRef tmp = _convertPercentEscapes(urlString, encoding, kCFStringEncodingUTF8, false, false, NULL, 0);
- CFRelease(urlString);
- urlString = tmp;
- if (!urlString) return NULL;
- }
- }
-
result = _CFURLAlloc(allocator);
if (result) {
+ if ( useEightBitStringEncoding ) {
+ ((struct __CFURL *)result)->_flags |= USES_EIGHTBITSTRINGENCODING;
+ }
_CFURLInitWithString(result, urlString, baseURL);
- if (encoding != kCFStringEncodingUTF8 && !createOldUTF8StyleURLs()) {
+ if (encoding != kCFStringEncodingUTF8) {
((struct __CFURL *)result)->_encoding = encoding;
- #if DEBUG_URL_MEMORY_USAGE
- if ( encoding != kCFStringEncodingUTF8 ) {
- numNonUTF8EncodedURLs++;
- }
- #endif
+#if DEBUG_URL_MEMORY_USAGE
+ numNonUTF8EncodedURLs++;
+#endif
}
}
CFRelease(urlString); // it's retained by result, now.
}
CFDataRef CFURLCreateData(CFAllocatorRef allocator, CFURLRef url, CFStringEncoding encoding, Boolean escapeWhitespace) {
- static const UniChar whitespaceChars[4] = {' ', '\n', '\r', '\t'};
- CFStringRef myStr = CFURLGetString(url);
- CFStringRef newStr;
- CFDataRef result;
- if (url->_flags & IS_OLD_UTF8_STYLE) {
- newStr = (encoding == kCFStringEncodingUTF8) ? (CFStringRef)CFRetain(myStr) : _convertPercentEscapes(myStr, kCFStringEncodingUTF8, encoding, true, false, escapeWhitespace ? whitespaceChars : NULL, escapeWhitespace ? 4 : 0);
- } else {
- newStr=myStr;
- CFRetain(newStr);
- }
- result = CFStringCreateExternalRepresentation(allocator, newStr, encoding, 0);
- CFRelease(newStr);
+ CFDataRef result = NULL;
+ if ( url ) {
+ CFStringRef myStr = CFURLGetString(url);
+ if ( myStr ) {
+ result = CFStringCreateExternalRepresentation(allocator, myStr, encoding, 0);
+ }
+ }
return result;
}
CFURLRef url;
if (!URLString || CFStringGetLength(URLString) == 0) return NULL;
if (!_CFStringIsLegalURLString(URLString)) return NULL;
-#if DEPLOYMENT_TARGET_MACOSX
- if ( !baseURL && CFStringGetCharacterAtIndex(URLString, 0) == '/' ) {
- CFLog(kCFLogLevelWarning, CFSTR("CFURLCreateWithString was passed this invalid URL string: '%@' (a file system path instead of an URL string). The URL created will not work with most file URL functions. CFURLCreateWithFileSystemPath or CFURLCreateWithFileSystemPathRelativeToBase should be used instead."), URLString);
- }
-#endif
url = _CFURLAlloc(allocator);
if (url) {
_CFURLInitWithString(url, URLString, baseURL);
}
CFURLRef CFURLCreateAbsoluteURLWithBytes(CFAllocatorRef alloc, const UInt8 *relativeURLBytes, CFIndex length, CFStringEncoding encoding, CFURLRef baseURL, Boolean useCompatibilityMode) {
- CFStringRef relativeString = CFStringCreateWithBytes(alloc, relativeURLBytes, length, encoding, false);
- if (!relativeString) {
- return NULL;
- }
-#if DEPLOYMENT_TARGET_MACOSX
- if ( !baseURL && *relativeURLBytes == '/' ) {
- CFLog(kCFLogLevelWarning, CFSTR("CFURLCreateAbsoluteURLWithBytes was passed these invalid relativeURLBytes (and no baseURL): '%@' (a file system path instead of an URL string). The URL created will not work with most file URL functions. CFURLCreateFromFileSystemRepresentationRelativeToBase should be used instead."), relativeString);
- }
-#endif
- if (!useCompatibilityMode) {
- CFURLRef url = _CFURLCreateWithArbitraryString(alloc, relativeString, baseURL);
- CFRelease(relativeString);
- if (url) {
- ((struct __CFURL *)url)->_encoding = encoding;
- CFURLRef absURL = CFURLCopyAbsoluteURL(url);
- #if DEBUG_URL_MEMORY_USAGE
- if ( encoding != kCFStringEncodingUTF8 ) {
- numNonUTF8EncodedURLs++;
- }
- #endif
- CFRelease(url);
- return absURL;
- } else {
- return NULL;
+ CFURLRef result = NULL;
+
+ // if not useCompatibilityMode, use CFURLCreateWithBytes and then CFURLCopyAbsoluteURL if there's a baseURL
+ if ( !useCompatibilityMode ) {
+ CFURLRef url = CFURLCreateWithBytes(alloc, relativeURLBytes, length, encoding, baseURL);
+ if ( url != NULL ) {
+ if ( baseURL != NULL ) {
+ result = CFURLCopyAbsoluteURL(url);
+ CFRelease(url);
+ } else {
+ result = url;
+ }
}
} else {
UInt32 absFlags = 0;
CFStringRef absString = NULL;
Boolean absStringIsMutable = false;
CFURLRef absURL;
- if (!baseURL) {
- absString = relativeString;
- } else {
- UniChar ch = CFStringGetCharacterAtIndex(relativeString, 0);
- if (ch == '?' || ch == ';' || ch == '#') {
- // Nothing but parameter + query + fragment; append to the baseURL string
- CFStringRef baseString;
- if (CF_IS_OBJC(__kCFURLTypeID, baseURL)) {
- baseString = CFURLGetString(baseURL);
- } else {
- baseString = baseURL->_string;
+ CFStringRef relativeString;
+ Boolean useEightBitStringEncoding;
+
+ useEightBitStringEncoding = ( __CFStringEncodingIsSupersetOfASCII(encoding) && __CFBytesInASCII(relativeURLBytes, length) );
+ relativeString = CFStringCreateWithBytes(alloc, relativeURLBytes, length, useEightBitStringEncoding ? __CFStringGetEightBitStringEncoding() : encoding, false);
+ if ( relativeString != NULL ) {
+ if (!baseURL) {
+ if ( useEightBitStringEncoding ) {
+ absFlags |= USES_EIGHTBITSTRINGENCODING;
}
- absString = CFStringCreateMutable(alloc, CFStringGetLength(baseString) + CFStringGetLength(relativeString));
- CFStringAppend((CFMutableStringRef)absString, baseString);
- CFStringAppend((CFMutableStringRef)absString, relativeString);
- absStringIsMutable = true;
+ absString = relativeString;
} else {
- UInt32 relFlags = 0;
- CFRange *relRanges;
- CFStringRef relString = NULL;
- _parseComponents(alloc, relativeString, baseURL, &relFlags, &relRanges);
- if (relFlags & HAS_SCHEME) {
- CFStringRef baseScheme = CFURLCopyScheme(baseURL);
- CFRange relSchemeRange = _rangeForComponent(relFlags, relRanges, HAS_SCHEME);
- if (baseScheme && CFStringGetLength(baseScheme) == relSchemeRange.length && CFStringHasPrefix(relativeString, baseScheme)) {
- relString = CFStringCreateWithSubstring(alloc, relativeString, CFRangeMake(relSchemeRange.length+1, CFStringGetLength(relativeString) - relSchemeRange.length - 1));
- CFAllocatorDeallocate(alloc, relRanges);
- relFlags = 0;
- _parseComponents(alloc, relString, baseURL, &relFlags, &relRanges);
+ UniChar ch = CFStringGetCharacterAtIndex(relativeString, 0);
+ if (ch == '?' || ch == ';' || ch == '#') {
+ // Nothing but parameter + query + fragment; append to the baseURL string
+ CFStringRef baseString;
+ if (CF_IS_OBJC(__kCFURLTypeID, baseURL)) {
+ baseString = CFURLGetString(baseURL);
} else {
- // Discard the base string; the relative string is absolute and we're not in the funky edge case where the schemes match
- CFRetain(relativeString);
- absString = relativeString;
+ baseString = baseURL->_string;
}
- if (baseScheme) CFRelease(baseScheme);
+ absString = CFStringCreateMutable(alloc, CFStringGetLength(baseString) + CFStringGetLength(relativeString));
+ CFStringAppend((CFMutableStringRef)absString, baseString);
+ CFStringAppend((CFMutableStringRef)absString, relativeString);
+ absStringIsMutable = true;
} else {
- CFRetain(relativeString);
- relString = relativeString;
- }
- if (!absString) {
- if (!CF_IS_OBJC(__kCFURLTypeID, baseURL)) {
- if (!(baseURL->_flags & IS_PARSED)) {
- _parseComponentsOfURL(baseURL);
+ UInt32 relFlags = 0;
+ CFRange *relRanges;
+ CFStringRef relString = NULL;
+ _parseComponents(alloc, relativeString, baseURL, &relFlags, &relRanges);
+ if (relFlags & HAS_SCHEME) {
+ CFStringRef baseScheme = CFURLCopyScheme(baseURL);
+ CFRange relSchemeRange = _rangeForComponent(relFlags, relRanges, HAS_SCHEME);
+ if (baseScheme && CFStringGetLength(baseScheme) == relSchemeRange.length && CFStringHasPrefix(relativeString, baseScheme)) {
+ relString = CFStringCreateWithSubstring(alloc, relativeString, CFRangeMake(relSchemeRange.length+1, CFStringGetLength(relativeString) - relSchemeRange.length - 1));
+ CFAllocatorDeallocate(alloc, relRanges);
+ relFlags = 0;
+ _parseComponents(alloc, relString, baseURL, &relFlags, &relRanges);
+ } 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;
}
- absString = resolveAbsoluteURLString(alloc, relString, relFlags, relRanges, baseURL->_string, baseURL->_flags, baseURL->ranges);
+ if (baseScheme) CFRelease(baseScheme);
} else {
- CFStringRef baseString;
- UInt32 baseFlags = 0;
- CFRange *baseRanges;
- if (CF_IS_OBJC(__kCFURLTypeID, baseURL)) {
- baseString = CFURLGetString(baseURL);
+ CFRetain(relativeString);
+ relString = relativeString;
+ }
+ if (!absString) {
+ if (!CF_IS_OBJC(__kCFURLTypeID, baseURL)) {
+ absString = resolveAbsoluteURLString(alloc, relString, relFlags, relRanges, baseURL->_string, baseURL->_flags, baseURL->_ranges);
} else {
- baseString = baseURL->_string;
+ CFStringRef baseString;
+ UInt32 baseFlags = 0;
+ CFRange *baseRanges;
+ if (CF_IS_OBJC(__kCFURLTypeID, baseURL)) {
+ baseString = CFURLGetString(baseURL);
+ } else {
+ baseString = baseURL->_string;
+ }
+ _parseComponents(alloc, baseString, NULL, &baseFlags, &baseRanges);
+ absString = resolveAbsoluteURLString(alloc, relString, relFlags, relRanges, baseString, baseFlags, baseRanges);
+ CFAllocatorDeallocate(alloc, baseRanges);
}
- _parseComponents(alloc, baseString, NULL, &baseFlags, &baseRanges);
- absString = resolveAbsoluteURLString(alloc, relString, relFlags, relRanges, baseString, baseFlags, baseRanges);
- CFAllocatorDeallocate(alloc, baseRanges);
+ absStringIsMutable = true;
}
- absStringIsMutable = true;
+ if (relString) CFRelease(relString);
+ CFAllocatorDeallocate(alloc, relRanges);
+ }
+ CFRelease(relativeString);
+ }
+ }
+ if ( absString ) {
+ _parseComponents(alloc, absString, NULL, &absFlags, &absRanges);
+ if (absFlags & HAS_PATH) {
+ CFRange pathRg = _rangeForComponent(absFlags, absRanges, HAS_PATH);
+ // This is expensive, but it allows us to reuse _resolvedPath. It should be cleaned up to get this allocation removed at some point. - REW
+ UniChar *buf = (UniChar *)CFAllocatorAllocate(alloc, sizeof(UniChar) * (pathRg.length + 1), 0);
+ CFStringRef newPath;
+ CFStringGetCharacters(absString, pathRg, buf);
+ buf[pathRg.length] = '\0';
+ newPath = _resolvedPath(buf, buf + pathRg.length, '/', true, false, alloc);
+ if (CFStringGetLength(newPath) != pathRg.length) {
+ if (!absStringIsMutable) {
+ CFStringRef tmp = CFStringCreateMutableCopy(alloc, CFStringGetLength(absString), absString);
+ CFRelease(absString);
+ absString = tmp;
+ }
+ CFStringReplace((CFMutableStringRef)absString, pathRg, newPath);
}
- if (relString) CFRelease(relString);
- CFAllocatorDeallocate(alloc, relRanges);
+ CFRelease(newPath);
+ // Do not deallocate buf; newPath took ownership of it.
}
- CFRelease(relativeString);
- }
- _parseComponents(alloc, absString, NULL, &absFlags, &absRanges);
- if (absFlags & HAS_PATH) {
- CFRange pathRg = _rangeForComponent(absFlags, absRanges, HAS_PATH);
- // This is expensive, but it allows us to reuse _resolvedPath. It should be cleaned up to get this allocation removed at some point. - REW
- UniChar *buf = (UniChar *)CFAllocatorAllocate(alloc, sizeof(UniChar) * (pathRg.length + 1), 0);
- CFStringRef newPath;
- CFStringGetCharacters(absString, pathRg, buf);
- buf[pathRg.length] = '\0';
- newPath = _resolvedPath(buf, buf + pathRg.length, '/', true, false, alloc);
- if (CFStringGetLength(newPath) != pathRg.length) {
- if (!absStringIsMutable) {
- CFStringRef tmp = CFStringCreateMutableCopy(alloc, CFStringGetLength(absString), absString);
- CFRelease(absString);
- absString = tmp;
+ CFAllocatorDeallocate(alloc, absRanges);
+ absURL = _CFURLCreateWithArbitraryString(alloc, absString, NULL);
+ CFRelease(absString);
+ if (absURL) {
+ ((struct __CFURL *)absURL)->_encoding = encoding;
+#if DEBUG_URL_MEMORY_USAGE
+ if ( encoding != kCFStringEncodingUTF8 ) {
+ numNonUTF8EncodedURLs++;
}
- CFStringReplace((CFMutableStringRef)absString, pathRg, newPath);
+#endif
}
- CFRelease(newPath);
- // Do not deallocate buf; newPath took ownership of it.
- }
- CFAllocatorDeallocate(alloc, absRanges);
- absURL = _CFURLCreateWithArbitraryString(alloc, absString, NULL);
- CFRelease(absString);
- if (absURL) {
- ((struct __CFURL *)absURL)->_encoding = encoding;
- #if DEBUG_URL_MEMORY_USAGE
- if ( encoding != kCFStringEncodingUTF8 ) {
- numNonUTF8EncodedURLs++;
- }
- #endif
+ result = absURL;
}
- return absURL;
}
+
+ return ( result );
}
/* This function is this way because I pulled it out of _resolvedURLPath (so that _resolvedFileSystemPath could use it), and I didn't want to spend a bunch of energy reworking the code. So instead of being a bit more intelligent about inputs, it just demands a slightly perverse set of parameters, to match the old _resolvedURLPath code. -- REW, 6/14/99 */
CFURLRef CFURLCopyAbsoluteURL(CFURLRef relativeURL) {
CFURLRef anURL, base;
- CFURLPathStyle fsType;
CFAllocatorRef alloc = CFGetAllocator(relativeURL);
CFStringRef baseString, newString;
UInt32 baseFlags;
CFAssert1(relativeURL != NULL, __kCFLogAssertion, "%s(): Cannot create an absolute URL from a NULL relative URL", __PRETTY_FUNCTION__);
if (CF_IS_OBJC(__kCFURLTypeID, relativeURL)) {
- CF_OBJC_CALL0(CFURLRef, anURL, relativeURL, "absoluteURL");
+ anURL = (CFURLRef) CF_OBJC_CALLV((NSURL *)relativeURL, absoluteURL);
if (anURL) CFRetain(anURL);
return anURL;
}
return (CFURLRef)CFRetain(relativeURL);
}
baseIsObjC = CF_IS_OBJC(__kCFURLTypeID, base);
- fsType = URL_PATH_TYPE(relativeURL);
-
- if (!baseIsObjC && fsType != FULL_URL_REPRESENTATION && fsType == URL_PATH_TYPE(base)) {
- return _CFURLCopyAbsoluteFileURL(relativeURL);
- }
- if (fsType != FULL_URL_REPRESENTATION) {
- _convertToURLRepresentation((struct __CFURL *)relativeURL);
- fsType = FULL_URL_REPRESENTATION;
- }
- if (!(relativeURL->_flags & IS_PARSED)) {
- _parseComponentsOfURL(relativeURL);
- }
- if ((relativeURL->_flags & POSIX_AND_URL_PATHS_MATCH) && !(relativeURL->_flags & (RESOURCE_SPECIFIER_MASK | NET_LOCATION_MASK)) && !baseIsObjC && (URL_PATH_TYPE(base) == kCFURLPOSIXPathStyle)) {
- // There's nothing to relativeURL's string except the path
- CFStringRef newPath = _resolveFileSystemPaths(relativeURL->_string, base->_string, CFURLHasDirectoryPath(base), kCFURLPOSIXPathStyle, alloc);
- CFURLRef result = CFURLCreateWithFileSystemPath(alloc, newPath, kCFURLPOSIXPathStyle, CFURLHasDirectoryPath(relativeURL));
- CFRelease(newPath);
- return result;
- }
if (!baseIsObjC) {
- CFURLPathStyle baseType = URL_PATH_TYPE(base);
- if (baseType != FULL_URL_REPRESENTATION) {
- _convertToURLRepresentation((struct __CFURL *)base);
- } else if (!(base->_flags & IS_PARSED)) {
- _parseComponentsOfURL(base);
- }
baseString = base->_string;
baseFlags = base->_flags;
- baseRanges = base->ranges;
+ baseRanges = base->_ranges;
} else {
baseString = CFURLGetString(base);
baseFlags = 0;
_parseComponents(alloc, baseString, NULL, &baseFlags, &baseRanges);
}
- newString = resolveAbsoluteURLString(alloc, relativeURL->_string, relativeURL->_flags, relativeURL->ranges, baseString, baseFlags, baseRanges);
+ newString = resolveAbsoluteURLString(alloc, relativeURL->_string, relativeURL->_flags, relativeURL->_ranges, baseString, baseFlags, baseRanges);
if (baseIsObjC) {
CFAllocatorDeallocate(alloc, baseRanges);
}
Boolean CFURLCanBeDecomposed(CFURLRef anURL) {
anURL = _CFURLFromNSURL(anURL);
- if (URL_PATH_TYPE(anURL) != FULL_URL_REPRESENTATION) return true;
- if (!(anURL->_flags & IS_PARSED)) {
- _parseComponentsOfURL(anURL);
- }
return ((anURL->_flags & IS_DECOMPOSABLE) != 0);
}
CFStringRef CFURLGetString(CFURLRef url) {
- CF_OBJC_FUNCDISPATCH0(__kCFURLTypeID, CFStringRef , url, "relativeString");
- if (URL_PATH_TYPE(url) != FULL_URL_REPRESENTATION) {
- if (url->_base && (url->_flags & POSIX_AND_URL_PATHS_MATCH)) {
- return url->_string;
- }
- _convertToURLRepresentation((struct __CFURL *)url);
- }
+ CF_OBJC_FUNCDISPATCHV(__kCFURLTypeID, CFStringRef, (NSURL *)url, relativeString);
if (!_haveTestedOriginalString(url)) {
computeSanitizedString(url);
}
string = CFURLGetString(url);
enc = kCFStringEncodingUTF8;
} else {
- if (URL_PATH_TYPE(url) != FULL_URL_REPRESENTATION) {
- _convertToURLRepresentation((struct __CFURL *)url);
- }
string = url->_string;
enc = url->_encoding;
}
}
CFURLRef CFURLGetBaseURL(CFURLRef anURL) {
- CF_OBJC_FUNCDISPATCH0(__kCFURLTypeID, CFURLRef, anURL, "baseURL");
+ CF_OBJC_FUNCDISPATCHV(__kCFURLTypeID, CFURLRef, (NSURL *)anURL, baseURL);
return anURL->_base;
}
CFRange rg;
CFStringRef comp;
CFAllocatorRef alloc = CFGetAllocator(url);
- CFAssert1(URL_PATH_TYPE(url) == FULL_URL_REPRESENTATION, __kCFLogAssertion, "%s(): passed a file system URL", __PRETTY_FUNCTION__);
- if (removePercentEscapes) fromOriginalString = true;
- if (!(url->_flags & IS_PARSED)) {
- _parseComponentsOfURL(url);
+ if (removePercentEscapes) {
+ fromOriginalString = true;
}
- rg = _rangeForComponent(url->_flags, url->ranges, compFlag);
- if (rg.location == kCFNotFound) return NULL;
- if (compFlag & HAS_SCHEME && url->_flags & HAS_HTTP_SCHEME) {
- comp = kCFURLHTTPScheme;
- CFRetain(comp);
- } else if (compFlag & HAS_SCHEME && url->_flags & HAS_FILE_SCHEME) {
- comp = kCFURLFileScheme;
- CFRetain(comp);
- } else {
- comp = CFStringCreateWithSubstring(alloc, url->_string, rg);
- }
- if (!fromOriginalString) {
- if (!_haveTestedOriginalString(url)) {
- computeSanitizedString(url);
+ rg = _rangeForComponent(url->_flags, url->_ranges, compFlag);
+ if (rg.location == kCFNotFound) {
+ comp = NULL;
+ }
+ else {
+ if ( compFlag & HAS_SCHEME ) {
+ switch ( _getSchemeTypeFromFlags(url->_flags) ) {
+ case kHasHttpScheme:
+ comp = (CFStringRef)CFRetain(kCFURLHTTPScheme);
+ break;
+
+ case kHasHttpsScheme:
+ comp = (CFStringRef)CFRetain(kCFURLHTTPSScheme);
+ break;
+
+ case kHasFileScheme:
+ comp = (CFStringRef)CFRetain(kCFURLFileScheme);
+ break;
+
+ case kHasDataScheme:
+ comp = (CFStringRef)CFRetain(kCFURLDataScheme);
+ break;
+
+ case kHasFtpScheme:
+ comp = (CFStringRef)CFRetain(kCFURLFTPScheme);
+ break;
+
+ default:
+ comp = CFStringCreateWithSubstring(alloc, url->_string, rg);
+ break;
+ }
}
- if (!(url->_flags & ORIGINAL_AND_URL_STRINGS_MATCH) && (url->_flags & (compFlag << BIT_SHIFT_FROM_COMPONENT_TO_DIFFERS_FLAG))) {
- CFStringRef newComp = correctedComponent(comp, compFlag, url->_encoding);
- CFRelease(comp);
- comp = newComp;
+ else {
+ comp = CFStringCreateWithSubstring(alloc, url->_string, rg);
}
- }
- if (removePercentEscapes) {
- CFStringRef tmp;
- if (url->_flags & IS_OLD_UTF8_STYLE || url->_encoding == kCFStringEncodingUTF8) {
- tmp = CFURLCreateStringByReplacingPercentEscapes(alloc, comp, CFSTR(""));
- } else {
- tmp = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(alloc, comp, CFSTR(""), url->_encoding);
+
+ if (!fromOriginalString) {
+ if (!_haveTestedOriginalString(url)) {
+ computeSanitizedString(url);
+ }
+ if (!(url->_flags & ORIGINAL_AND_URL_STRINGS_MATCH) && (_getAdditionalDataFlags(url) & compFlag)) {
+ CFStringRef newComp = correctedComponent(comp, compFlag, url->_encoding);
+ CFRelease(comp);
+ comp = newComp;
+ }
}
- CFRelease(comp);
- comp = tmp;
+ if (removePercentEscapes) {
+ CFStringRef tmp;
+ if (url->_encoding == kCFStringEncodingUTF8) {
+ tmp = CFURLCreateStringByReplacingPercentEscapes(alloc, comp, CFSTR(""));
+ } else {
+ tmp = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(alloc, comp, CFSTR(""), url->_encoding);
+ }
+ CFRelease(comp);
+ comp = tmp;
+ }
+
}
return comp;
}
CFStringRef CFURLCopyScheme(CFURLRef anURL) {
CFStringRef scheme;
if (CF_IS_OBJC(__kCFURLTypeID, anURL)) {
- CF_OBJC_CALL0(CFStringRef, scheme, anURL, "scheme");
- if (scheme) CFRetain(scheme);
- return scheme;
- }
- if (URL_PATH_TYPE(anURL) != FULL_URL_REPRESENTATION) {
- if (anURL->_base) {
- return CFURLCopyScheme(anURL->_base);
- } else {
- CFRetain(kCFURLFileScheme); // because caller will release it
- return kCFURLFileScheme;
+ scheme = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, scheme);
+ if ( scheme ) {
+ CFRetain(scheme);
}
- }
- if (anURL->_flags & IS_PARSED && anURL->_flags & HAS_HTTP_SCHEME) {
- CFRetain(kCFURLHTTPScheme);
- return kCFURLHTTPScheme;
}
- if (anURL->_flags & IS_PARSED && anURL->_flags & HAS_FILE_SCHEME) {
- CFRetain(kCFURLFileScheme);
- return kCFURLFileScheme;
- }
- scheme = _retainedComponentString(anURL, HAS_SCHEME, true, false);
- if (scheme) {
- return scheme;
- } else if (anURL->_base) {
- return CFURLCopyScheme(anURL->_base);
- } else {
- return NULL;
+ else {
+ switch ( _getSchemeTypeFromFlags(anURL->_flags) ) {
+ case kHasHttpScheme:
+ scheme = (CFStringRef)CFRetain(kCFURLHTTPScheme);
+ break;
+
+ case kHasHttpsScheme:
+ scheme = (CFStringRef)CFRetain(kCFURLHTTPSScheme);
+ break;
+
+ case kHasFileScheme:
+ scheme = (CFStringRef)CFRetain(kCFURLFileScheme);
+ break;
+
+ case kHasDataScheme:
+ scheme = (CFStringRef)CFRetain(kCFURLDataScheme);
+ break;
+
+ case kHasFtpScheme:
+ scheme = (CFStringRef)CFRetain(kCFURLFTPScheme);
+ break;
+
+ default:
+ scheme = _retainedComponentString(anURL, HAS_SCHEME, true, false);
+ if ( !scheme ) {
+ if (anURL->_base) {
+ scheme = CFURLCopyScheme(anURL->_base);
+ } else {
+ scheme = NULL;
+ }
+ }
+ break;
+ }
}
+ return ( scheme );
}
static CFRange _netLocationRange(UInt32 flags, CFRange *ranges) {
CFStringRef CFURLCopyNetLocation(CFURLRef anURL) {
anURL = _CFURLFromNSURL(anURL);
- if (URL_PATH_TYPE(anURL) != FULL_URL_REPRESENTATION) {
- // !!! This won't work if we go to putting the vol ref num in the net location for HFS
- if (anURL->_base) {
- return CFURLCopyNetLocation(anURL->_base);
- } else {
- CFRetain(kCFURLLocalhost);
- return kCFURLLocalhost;
- }
- }
- if (!(anURL->_flags & IS_PARSED)) {
- _parseComponentsOfURL(anURL);
- }
if (anURL->_flags & NET_LOCATION_MASK) {
// We provide the net location
- CFRange netRg = _netLocationRange(anURL->_flags, anURL->ranges);
+ CFRange netRg = _netLocationRange(anURL->_flags, anURL->_ranges);
CFStringRef netLoc;
if (!_haveTestedOriginalString(anURL)) {
computeSanitizedString(anURL);
}
- if (!(anURL->_flags & ORIGINAL_AND_URL_STRINGS_MATCH) && (anURL->_flags & (USER_DIFFERS | PASSWORD_DIFFERS | HOST_DIFFERS | PORT_DIFFERS))) {
+ if (!(anURL->_flags & ORIGINAL_AND_URL_STRINGS_MATCH) && (_getAdditionalDataFlags(anURL) & (USER_DIFFERS | PASSWORD_DIFFERS | HOST_DIFFERS | PORT_DIFFERS))) {
// Only thing that can come before the net location is the scheme. It's impossible for the scheme to contain percent escapes. Therefore, we can use the location of netRg in _sanatizedString, just not the length.
CFRange netLocEnd;
- netRg.length = CFStringGetLength( _getSanitizedString(anURL)) - netRg.location;
- if (CFStringFindWithOptions(_getSanitizedString(anURL), CFSTR("/"), netRg, 0, &netLocEnd)) {
+ CFStringRef sanitizedString = _getSanitizedString(anURL);
+ netRg.length = CFStringGetLength(sanitizedString) - netRg.location;
+ if (CFStringFindWithOptions(sanitizedString, CFSTR("/"), netRg, 0, &netLocEnd)) {
netRg.length = netLocEnd.location - netRg.location;
}
- netLoc = CFStringCreateWithSubstring(CFGetAllocator(anURL), _getSanitizedString(anURL), netRg);
+ netLoc = CFStringCreateWithSubstring(CFGetAllocator(anURL), sanitizedString, netRg);
} else {
netLoc = CFStringCreateWithSubstring(CFGetAllocator(anURL), anURL->_string, netRg);
}
// NOTE - if you want an absolute path, you must first get the absolute URL. If you want a file system path, use the file system methods above.
CFStringRef CFURLCopyPath(CFURLRef anURL) {
anURL = _CFURLFromNSURL(anURL);
- if (URL_PATH_TYPE(anURL) == kCFURLPOSIXPathStyle && (anURL->_flags & POSIX_AND_URL_PATHS_MATCH)) {
- CFRetain(anURL->_string);
- return anURL->_string;
- }
- if (URL_PATH_TYPE(anURL) != FULL_URL_REPRESENTATION) {
- _convertToURLRepresentation((struct __CFURL *)anURL);
- }
return _retainedComponentString(anURL, HAS_PATH, false, false);
}
Boolean CFURLHasDirectoryPath(CFURLRef anURL) {
__CFGenericValidateType(anURL, __kCFURLTypeID);
- if (URL_PATH_TYPE(anURL) == FULL_URL_REPRESENTATION) {
- if (!(anURL->_flags & IS_PARSED)) {
- _parseComponentsOfURL(anURL);
- }
- if (!anURL->_base || (anURL->_flags & (HAS_PATH | NET_LOCATION_MASK))) {
- return ((anURL->_flags & IS_DIRECTORY) != 0);
- }
+ if (!anURL->_base || (anURL->_flags & (HAS_PATH | NET_LOCATION_MASK))) {
+ return ((anURL->_flags & IS_DIRECTORY) != 0);
+ }
+ else {
return CFURLHasDirectoryPath(anURL->_base);
}
- return ((anURL->_flags & IS_DIRECTORY) != 0);
}
static UInt32 _firstResourceSpecifierFlag(UInt32 flags) {
CFStringRef CFURLCopyResourceSpecifier(CFURLRef anURL) {
anURL = _CFURLFromNSURL(anURL);
__CFGenericValidateType(anURL, __kCFURLTypeID);
- if (URL_PATH_TYPE(anURL) != FULL_URL_REPRESENTATION) {
- return NULL;
- }
- if (!(anURL->_flags & IS_PARSED)) {
- _parseComponentsOfURL(anURL);
- }
if (!(anURL->_flags & IS_DECOMPOSABLE)) {
- CFRange schemeRg = _rangeForComponent(anURL->_flags, anURL->ranges, HAS_SCHEME);
+ CFRange schemeRg = _rangeForComponent(anURL->_flags, anURL->_ranges, HAS_SCHEME);
CFIndex base = schemeRg.location + schemeRg.length + 1;
if (!_haveTestedOriginalString(anURL)) {
computeSanitizedString(anURL);
}
- if (_getSanitizedString(anURL)) {
+
+ CFStringRef sanitizedString = _getSanitizedString(anURL);
+
+ if (sanitizedString) {
// It is impossible to have a percent escape in the scheme (if there were one, we would have considered the URL a relativeURL with a colon in the path instead), so this range computation is always safe.
- return CFStringCreateWithSubstring(CFGetAllocator(anURL), _getSanitizedString(anURL), CFRangeMake(base, CFStringGetLength(_getSanitizedString(anURL))-base));
+ return CFStringCreateWithSubstring(CFGetAllocator(anURL), sanitizedString, CFRangeMake(base, CFStringGetLength(sanitizedString)-base));
} else {
return CFStringCreateWithSubstring(CFGetAllocator(anURL), anURL->_string, CFRangeMake(base, CFStringGetLength(anURL->_string)-base));
}
if (!_haveTestedOriginalString(anURL)) {
computeSanitizedString(anURL);
}
+
+ UInt32 additionalDataFlags = _getAdditionalDataFlags(anURL);
+ CFStringRef sanitizedString = _getSanitizedString(anURL);
+
if (!(anURL->_flags & ORIGINAL_AND_URL_STRINGS_MATCH)) {
// See if any pieces in the resource specifier differ between sanitized string and original string
for (flag = firstRsrcSpecFlag; flag != (HAS_FRAGMENT << 1); flag = flag << 1) {
- if (anURL->_flags & (flag << BIT_SHIFT_FROM_COMPONENT_TO_DIFFERS_FLAG)) {
+ if (additionalDataFlags & flag) {
canUseOriginalString = false;
break;
}
if (!canUseOriginalString) {
// If none of the pieces prior to the first resource specifier flag differ, then we can use the offset from the original string as the offset in the sanitized string.
for (flag = firstRsrcSpecFlag >> 1; flag != 0; flag = flag >> 1) {
- if (anURL->_flags & (flag << BIT_SHIFT_FROM_COMPONENT_TO_DIFFERS_FLAG)) {
+ if (additionalDataFlags & flag) {
canUseSanitizedString = false;
break;
}
}
}
if (canUseOriginalString) {
- CFRange rg = _rangeForComponent(anURL->_flags, anURL->ranges, firstRsrcSpecFlag);
+ CFRange rg = _rangeForComponent(anURL->_flags, anURL->_ranges, firstRsrcSpecFlag);
rg.location --; // Include the character that demarcates the component
rg.length = CFStringGetLength(anURL->_string) - rg.location;
return CFStringCreateWithSubstring(alloc, anURL->_string, rg);
} else if (canUseSanitizedString) {
- CFRange rg = _rangeForComponent(anURL->_flags, anURL->ranges, firstRsrcSpecFlag);
+ CFRange rg = _rangeForComponent(anURL->_flags, anURL->_ranges, firstRsrcSpecFlag);
rg.location --; // Include the character that demarcates the component
- rg.length = CFStringGetLength(_getSanitizedString(anURL)) - rg.location;
- return CFStringCreateWithSubstring(alloc, _getSanitizedString(anURL), rg);
+ rg.length = CFStringGetLength(sanitizedString) - rg.location;
+ return CFStringCreateWithSubstring(alloc, sanitizedString, rg);
} else {
// Must compute the correct string to return; just reparse....
UInt32 sanFlags = 0;
CFRange *sanRanges = NULL;
CFRange rg;
- _parseComponents(alloc, _getSanitizedString(anURL), anURL->_base, &sanFlags, &sanRanges);
+ _parseComponents(alloc, sanitizedString, anURL->_base, &sanFlags, &sanRanges);
rg = _rangeForComponent(sanFlags, sanRanges, firstRsrcSpecFlag);
CFAllocatorDeallocate(alloc, sanRanges);
rg.location --; // Include the character that demarcates the component
- rg.length = CFStringGetLength(_getSanitizedString(anURL)) - rg.location;
- return CFStringCreateWithSubstring(CFGetAllocator(anURL), _getSanitizedString(anURL), rg);
+ rg.length = CFStringGetLength(sanitizedString) - rg.location;
+ return CFStringCreateWithSubstring(CFGetAllocator(anURL), sanitizedString, rg);
}
} else {
// The resource specifier cannot possibly come from the base.
CFStringRef CFURLCopyHostName(CFURLRef anURL) {
CFStringRef tmp;
if (CF_IS_OBJC(__kCFURLTypeID, anURL)) {
- CF_OBJC_CALL0(CFStringRef, tmp, anURL, "host");
+ tmp = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, host);
if (tmp) CFRetain(tmp);
return tmp;
}
__CFGenericValidateType(anURL, __kCFURLTypeID);
- if (URL_PATH_TYPE(anURL) != FULL_URL_REPRESENTATION) {
- if (anURL->_base) {
- return CFURLCopyHostName(anURL->_base);
- } else {
- CFRetain(kCFURLLocalhost);
- return kCFURLLocalhost;
- }
- }
tmp = _retainedComponentString(anURL, HAS_HOST, true, true);
if (tmp) {
if (anURL->_flags & IS_IPV6_ENCODED) {
SInt32 CFURLGetPortNumber(CFURLRef anURL) {
CFStringRef port;
if (CF_IS_OBJC(__kCFURLTypeID, anURL)) {
- CFNumberRef cfPort;
- CF_OBJC_CALL0(CFNumberRef, cfPort, anURL, "port");
+ CFNumberRef cfPort = (CFNumberRef) CF_OBJC_CALLV((NSURL *)anURL, port);
SInt32 num;
if (cfPort && CFNumberGetValue(cfPort, kCFNumberSInt32Type, &num)) return num;
return -1;
}
__CFGenericValidateType(anURL, __kCFURLTypeID);
- if (URL_PATH_TYPE(anURL) != FULL_URL_REPRESENTATION) {
- if (anURL->_base) {
- return CFURLGetPortNumber(anURL->_base);
- }
- return -1;
- }
port = _retainedComponentString(anURL, HAS_PORT, true, false);
if (port) {
SInt32 portNum, idx, length = CFStringGetLength(port);
CFStringRef CFURLCopyUserName(CFURLRef anURL) {
CFStringRef user;
if (CF_IS_OBJC(__kCFURLTypeID, anURL)) {
- CF_OBJC_CALL0(CFStringRef, user, anURL, "user");
+ user = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, user);
if (user) CFRetain(user);
return user;
}
__CFGenericValidateType(anURL, __kCFURLTypeID);
- if (URL_PATH_TYPE(anURL) != FULL_URL_REPRESENTATION) {
- if (anURL->_base) {
- return CFURLCopyUserName(anURL->_base);
- }
- return NULL;
- }
user = _retainedComponentString(anURL, HAS_USER, true, true);
if (user) {
return user;
CFStringRef CFURLCopyPassword(CFURLRef anURL) {
CFStringRef passwd;
if (CF_IS_OBJC(__kCFURLTypeID, anURL)) {
- CF_OBJC_CALL0(CFStringRef, passwd, anURL, "password");
+ passwd = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, password);
if (passwd) CFRetain(passwd);
return passwd;
}
__CFGenericValidateType(anURL, __kCFURLTypeID);
- if (URL_PATH_TYPE(anURL) != FULL_URL_REPRESENTATION) {
- if (anURL->_base) {
- return CFURLCopyPassword(anURL->_base);
- }
- return NULL;
- }
passwd = _retainedComponentString(anURL, HAS_PASSWORD, true, true);
if (passwd) {
return passwd;
static CFStringRef _unescapedParameterString(CFURLRef anURL) {
CFStringRef str;
if (CF_IS_OBJC(__kCFURLTypeID, anURL)) {
- CF_OBJC_CALL0(CFStringRef, str, anURL, "parameterString");
+ str = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, parameterString);
if (str) CFRetain(str);
return str;
}
__CFGenericValidateType(anURL, __kCFURLTypeID);
- if (URL_PATH_TYPE(anURL) != FULL_URL_REPRESENTATION) {
- return NULL;
- }
str = _retainedComponentString(anURL, HAS_PARAMETERS, false, false);
if (str) return str;
if (!(anURL->_flags & IS_DECOMPOSABLE)) return NULL;
CFStringRef param = _unescapedParameterString(anURL);
if (param) {
CFStringRef result;
- if (anURL->_flags & IS_OLD_UTF8_STYLE || anURL->_encoding == kCFStringEncodingUTF8) {
+ if (anURL->_encoding == kCFStringEncodingUTF8) {
result = CFURLCreateStringByReplacingPercentEscapes(CFGetAllocator(anURL), param, charactersToLeaveEscaped);
} else {
result = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(CFGetAllocator(anURL), param, charactersToLeaveEscaped, anURL->_encoding);
static CFStringRef _unescapedQueryString(CFURLRef anURL) {
CFStringRef str;
if (CF_IS_OBJC(__kCFURLTypeID, anURL)) {
- CF_OBJC_CALL0(CFStringRef, str, anURL, "query");
+ str = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, query);
if (str) CFRetain(str);
return str;
}
__CFGenericValidateType(anURL, __kCFURLTypeID);
- if (URL_PATH_TYPE(anURL) != FULL_URL_REPRESENTATION) {
- return NULL;
- }
str = _retainedComponentString(anURL, HAS_QUERY, false, false);
if (str) return str;
if (!(anURL->_flags & IS_DECOMPOSABLE)) return NULL;
CFStringRef query = _unescapedQueryString(anURL);
if (query) {
CFStringRef tmp;
- if (anURL->_flags & IS_OLD_UTF8_STYLE || anURL->_encoding == kCFStringEncodingUTF8) {
+ if (anURL->_encoding == kCFStringEncodingUTF8) {
tmp = CFURLCreateStringByReplacingPercentEscapes(CFGetAllocator(anURL), query, charactersToLeaveEscaped);
} else {
tmp = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(CFGetAllocator(anURL), query, charactersToLeaveEscaped, anURL->_encoding);
static CFStringRef _unescapedFragment(CFURLRef anURL) {
CFStringRef str;
if (CF_IS_OBJC(__kCFURLTypeID, anURL)) {
- CF_OBJC_CALL0(CFStringRef, str, anURL, "fragment");
+ str = (CFStringRef) CF_OBJC_CALLV((NSURL *)anURL, fragment);
if (str) CFRetain(str);
return str;
}
__CFGenericValidateType(anURL, __kCFURLTypeID);
- if (URL_PATH_TYPE(anURL) != FULL_URL_REPRESENTATION) {
- return NULL;
- }
str = _retainedComponentString(anURL, HAS_FRAGMENT, false, false);
return str;
}
CFStringRef fragment = _unescapedFragment(anURL);
if (fragment) {
CFStringRef tmp;
- if (anURL->_flags & IS_OLD_UTF8_STYLE || anURL->_encoding == kCFStringEncodingUTF8) {
+ if (anURL->_encoding == kCFStringEncodingUTF8) {
tmp = CFURLCreateStringByReplacingPercentEscapes(CFGetAllocator(anURL), fragment, charactersToLeaveEscaped);
} else {
tmp = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(CFGetAllocator(anURL), fragment, charactersToLeaveEscaped, anURL->_encoding);
} else if (lastComponentBeforeMask == HAS_SCHEME) {
// Do not have to worry about the non-decomposable case here. However, we must be prepared for the degenerate
// case file:/path/immediately/without/host
- CFRange schemeRg = _rangeForComponent(url->_flags, url->ranges, HAS_SCHEME);
- CFRange pathRg = _rangeForComponent(url->_flags, url->ranges, HAS_PATH);
+ CFRange schemeRg = _rangeForComponent(url->_flags, url->_ranges, HAS_SCHEME);
+ CFRange pathRg = _rangeForComponent(url->_flags, url->_ranges, HAS_PATH);
if (schemeRg.length + 1 == pathRg.location) {
return schemeRg.length + 1;
} else {
} else {
// For all other components, the separator precedes the component, so there's no need
// to add extra chars to get to the next insertion point
- CFRange rg = _rangeForComponent(url->_flags, url->ranges, lastComponentBeforeMask);
+ CFRange rg = _rangeForComponent(url->_flags, url->_ranges, lastComponentBeforeMask);
return rg.location + rg.length;
}
}
Boolean haveReachedMask = false;
CFIndex beforeMask = 0;
CFIndex afterMask = kCFNotFound;
- CFRange *currRange = url->ranges;
+ CFRange *currRange = url->_ranges;
CFRange maskRange = {kCFNotFound, 0};
for (currentOption = 1; currentOption <= HAS_FRAGMENT; currentOption = currentOption << 1) {
if (!haveReachedMask && (currentOption & mask) != 0) {
static CFRange _getCharRangeInNonDecomposableURL(CFURLRef url, CFURLComponentType component, CFRange *rangeIncludingSeparators) {
if (component == kCFURLComponentScheme) {
- CFRange schemeRg = _rangeForComponent(url->_flags, url->ranges, HAS_SCHEME);
+ CFRange schemeRg = _rangeForComponent(url->_flags, url->_ranges, HAS_SCHEME);
rangeIncludingSeparators->location = 0;
rangeIncludingSeparators->length = schemeRg.length + 1;
return schemeRg;
} else if (component == kCFURLComponentResourceSpecifier) {
- CFRange schemeRg = _rangeForComponent(url->_flags, url->ranges, HAS_SCHEME);
+ CFRange schemeRg = _rangeForComponent(url->_flags, url->_ranges, HAS_SCHEME);
CFIndex stringLength = CFStringGetLength(url->_string);
if (schemeRg.length + 1 == stringLength) {
rangeIncludingSeparators->location = schemeRg.length + 1;
CFRange byteRange;
CFAssert2(component > 0 && component < 13, __kCFLogAssertion, "%s(): passed invalid component %d", __PRETTY_FUNCTION__, component);
url = _CFURLFromNSURL(url);
- if (URL_PATH_TYPE(url) != FULL_URL_REPRESENTATION) {
- _convertToURLRepresentation((struct __CFURL *)url);
- }
- if (!(url->_flags & IS_PARSED)) {
- _parseComponentsOfURL(url);
- }
if (!(url->_flags & IS_DECOMPOSABLE)) {
// Special-case this because non-decomposable URLs have a slightly strange flags setup
/* Component support */
-/* We convert to the CFURL immediately at the beginning of decomposition, so all the decomposition routines need not worry about having an ObjC NSURL */
-static CFStringRef schemeSpecificString(CFURLRef url) {
- Boolean isDir;
- isDir = ((url->_flags & IS_DIRECTORY) != 0);
- switch (URL_PATH_TYPE(url)) {
- case kCFURLPOSIXPathStyle:
- if (url->_flags & POSIX_AND_URL_PATHS_MATCH) {
- return (CFStringRef)CFRetain(url->_string);
- } else {
- return POSIXPathToURLPath(url->_string, CFGetAllocator(url), isDir);
- }
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
- case kCFURLHFSPathStyle:
- return HFSPathToURLPath(url->_string, CFGetAllocator(url), isDir);
-#endif
- case kCFURLWindowsPathStyle:
- return WindowsPathToURLPath(url->_string, CFGetAllocator(url), isDir);
- case FULL_URL_REPRESENTATION:
- return CFURLCopyResourceSpecifier(url);
- default:
- return NULL;
- }
-}
-
static Boolean decomposeToNonHierarchical(CFURLRef url, CFURLComponentsNonHierarchical *components) {
if ( CFURLGetBaseURL(url) != NULL) {
components->scheme = NULL;
} else {
components->scheme = CFURLCopyScheme(url);
}
- components->schemeSpecific = schemeSpecificString(url);
+ components->schemeSpecific = CFURLCopyResourceSpecifier(url);
return true;
}
static Boolean decomposeToRFC1808(CFURLRef url, CFURLComponentsRFC1808 *components) {
CFAllocatorRef alloc = CFGetAllocator(url);
- int pathType;
static CFStringRef emptyStr = NULL;
if (!emptyStr) {
emptyStr = CFSTR("");
if (!CFURLCanBeDecomposed(url)) {
return false;
}
- if ((pathType = URL_PATH_TYPE(url)) == FULL_URL_REPRESENTATION) {
- CFStringRef path = CFURLCopyPath(url);
- if (path) {
- components->pathComponents = CFStringCreateArrayBySeparatingStrings(alloc, path, CFSTR("/"));
- CFRelease(path);
- } else {
- components->pathComponents = NULL;
- }
- components->baseURL = CFURLGetBaseURL(url);
- if (components->baseURL) {
- CFRetain(components->baseURL);
- components->scheme = NULL;
- } else {
- components->scheme = _retainedComponentString(url, HAS_SCHEME, true, false);
- }
- components->user = _retainedComponentString(url, HAS_USER, false, false);
- components->password = _retainedComponentString(url, HAS_PASSWORD, false, false);
- components->host = _retainedComponentString(url, HAS_HOST, false, false);
- if (url->_flags & HAS_PORT) {
- components->port = CFURLGetPortNumber(url);
- } else {
- components->port = kCFNotFound;
- }
- components->parameterString = _retainedComponentString(url, HAS_PARAMETERS, false, false);
- components->query = _retainedComponentString(url, HAS_QUERY, false, false);
- components->fragment = _retainedComponentString(url, HAS_FRAGMENT, false, false);
+
+ CFStringRef path = CFURLCopyPath(url);
+ if (path) {
+ components->pathComponents = CFStringCreateArrayBySeparatingStrings(alloc, path, CFSTR("/"));
+ CFRelease(path);
+ } else {
+ components->pathComponents = NULL;
+ }
+ components->baseURL = CFURLGetBaseURL(url);
+ if (components->baseURL) {
+ CFRetain(components->baseURL);
+ components->scheme = NULL;
+ } else {
+ components->scheme = _retainedComponentString(url, HAS_SCHEME, true, false);
+ }
+ components->user = _retainedComponentString(url, HAS_USER, false, false);
+ components->password = _retainedComponentString(url, HAS_PASSWORD, false, false);
+ components->host = _retainedComponentString(url, HAS_HOST, false, false);
+ if (url->_flags & HAS_PORT) {
+ components->port = CFURLGetPortNumber(url);
} else {
- switch (pathType) {
- case kCFURLPOSIXPathStyle: {
- CFStringRef pathStr;
- if (url->_flags & POSIX_AND_URL_PATHS_MATCH) {
- pathStr = url->_string;
- CFRetain(pathStr);
- } else {
- pathStr = POSIXPathToURLPath(url->_string, alloc, url->_flags & IS_DIRECTORY);
- }
- components->pathComponents = CFStringCreateArrayBySeparatingStrings(alloc, pathStr, CFSTR("/"));
- CFRelease(pathStr);
- break;
- }
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
- case kCFURLHFSPathStyle:
- components->pathComponents = HFSPathToURLComponents(url->_string, alloc, ((url->_flags & IS_DIRECTORY) != 0));
- break;
-#endif
- case kCFURLWindowsPathStyle:
- components->pathComponents = WindowsPathToURLComponents(url->_string, alloc, ((url->_flags & IS_DIRECTORY) != 0));
- break;
- default:
- components->pathComponents = NULL;
- }
- if (!components->pathComponents) {
- return false;
- }
- components->scheme = (CFStringRef)CFRetain(kCFURLFileScheme);
- components->user = NULL;
- components->password = NULL;
- components->host = (CFStringRef)CFRetain(kCFURLLocalhost);
components->port = kCFNotFound;
- components->parameterString = NULL;
- components->query = NULL;
- components->fragment = NULL;
- components->baseURL = CFURLGetBaseURL(url);
- if (components->baseURL) CFRetain(components->baseURL);
}
+ components->parameterString = _retainedComponentString(url, HAS_PARAMETERS, false, false);
+ components->query = _retainedComponentString(url, HAS_QUERY, false, false);
+ components->fragment = _retainedComponentString(url, HAS_FRAGMENT, false, false);
return true;
}
}
return result;
}
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+static Boolean CanonicalFileURLStringToFileSystemRepresentation(CFStringRef str, CFAllocatorRef alloc, UInt8 *inBuffer, CFIndex inBufferLen)
+{
+ 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);
+ if ( strLength != 0 ) {
+ CFIndex maxBufLength = strLength * 3;
+ CFIndex usedBufLen;
+ CFIndex charsConverted;
+ if ( strLength <= PATH_MAX ) {
+ escapedBuf = &stackEscapedBuf[0];
+ }
+ else {
+ // worst case size is every unicode code point could be a 3-byte UTF8 sequence
+ escapedBuf = (UInt8 *)malloc(maxBufLength);
+ }
+ if ( escapedBuf != NULL ) {
+ charsConverted = CFStringGetBytes(str, CFRangeMake(sizeof(fileURLPrefixWithAuthority) - 1, strLength), kCFStringEncodingUTF8, 0, false, escapedBuf, maxBufLength, &usedBufLen);
+ if ( charsConverted ) {
+ static const UInt8 hexvalues[] = {
+ /* 00 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 08 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 10 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 18 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 20 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 28 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 30 */ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ /* 38 */ 0x8, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 40 */ 0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0,
+ /* 48 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 50 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 58 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 60 */ 0x0, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0,
+ /* 68 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 70 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 78 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+
+ /* 80 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 88 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 90 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* 98 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* A0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* A8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* B0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* B8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* C0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* C8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* D0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* D8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* E0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* E8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* F0 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ /* F8 */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ };
+ UInt8 *bufStartPtr;
+ UInt8 *bufEndPtr;
+ UInt8 *bufPtr;
+ const UInt8 *bytePtr = escapedBuf;
+ CFIndex idx;
+ Boolean trailingSlash = false;
+
+ bufPtr = bufStartPtr = inBuffer;
+ bufEndPtr = inBuffer + inBufferLen;
+ result = TRUE;
+
+ for ( idx = 0; (idx < usedBufLen) && result; ++idx ) {
+ if ( bufPtr == bufEndPtr ) {
+ // ooops, ran out of inBuffer
+ *bufStartPtr = '\0';
+ result = FALSE;
+ }
+ else {
+ switch ( *bytePtr ) {
+ case '%':
+ idx += 2;
+ if ( idx < usedBufLen ) {
+ // skip over %
+ bytePtr++;
+ // convert hex digits
+ *bufPtr = hexvalues[*bytePtr++] << 4;
+ *bufPtr += hexvalues[*bytePtr++];
+ trailingSlash = (*bufPtr == '/');
+ }
+ break;
+ default:
+ // copy everything else
+ *bufPtr = *bytePtr++;
+ trailingSlash = (*bufPtr == '/');
+ break;
+ }
+ ++bufPtr;
+ }
+ }
+ if ( result ) {
+ // remove trailing slash (if any)
+ if ( (bufPtr > (bufStartPtr + 1)) && trailingSlash ) {
+ --bufPtr;
+ }
+ if ( bufPtr < bufEndPtr ) {
+ *bufPtr = '\0';
+ }
+ }
+ }
+ else {
+ // CFStringGetBytes failed
+ result = FALSE;
+ }
+ // free the buffer if we malloc'd it
+ if ( escapedBuf != &stackEscapedBuf[0] ) {
+ free(escapedBuf);
+ }
+ }
+ else {
+ // could not allocate escapedBuf
+ result = FALSE;
+ }
+ }
+ else {
+ // str was zero characters
+ *inBuffer = '\0';
+ result = TRUE;
+ }
+ }
+ else {
+ // no inBuffer or inBufferLen is zero
+ result = FALSE;
+ }
+
+ return ( result );
+}
+#endif
+
#if DEPLOYMENT_TARGET_WINDOWS
// From CFPlatform.c
extern CFStringRef CFCreateWindowsDrivePathFromVolumeName(CFStringRef volNameStr);
// converts url from a file system path representation to a standard representation
-static void _convertToURLRepresentation(struct __CFURL *url) {
+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);
-#if DEBUG_URL_MEMORY_USAGE
- numFileURLsConverted ++;
-#endif
-
- switch (URL_PATH_TYPE(url)) {
+ switch (fsType) {
case kCFURLPOSIXPathStyle:
+ isFileReferencePath = _pathHasFileIDPrefix(url->_string);
if (url->_flags & POSIX_AND_URL_PATHS_MATCH) {
path = (CFStringRef)CFRetain(url->_string);
} else {
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://") : CFSTR("file://localhost"));
- CFStringAppend(str, path);
- url->_flags = (url->_flags & (IS_DIRECTORY)) | (FULL_URL_REPRESENTATION << 16) | IS_DECOMPOSABLE | IS_ABSOLUTE | IS_PARSED | HAS_SCHEME | HAS_FILE_SCHEME | HAS_HOST | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH | ( isFileReferencePath ? PATH_HAS_FILE_ID : 0 );
- CFRelease(url->_string);
- url->_string = str;
- url->ranges = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange) * 3, 0);
- url->ranges[0] = CFRangeMake(0, 4);
- url->ranges[1] = CFRangeMake(7, isFileReferencePath ? 0 : 9);
- url->ranges[2] = CFRangeMake(url->ranges[1].location + url->ranges[1].length, CFStringGetLength(path));
- CFRelease(path);
- } else {
- CFRelease(url->_string);
- url->_flags = (url->_flags & (IS_DIRECTORY)) | (FULL_URL_REPRESENTATION << 16) | IS_DECOMPOSABLE | IS_PARSED | HAS_PATH | ORIGINAL_AND_URL_STRINGS_MATCH;
- url->_string = path;
- url->ranges = (CFRange *)CFAllocatorAllocate(alloc, sizeof(CFRange), 0);
- *(url->ranges) = CFRangeMake(0, CFStringGetLength(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));
+ }
}
}
-// relativeURL is known to be a file system URL whose base is a matching file system URL
-static CFURLRef _CFURLCopyAbsoluteFileURL(CFURLRef relativeURL) {
- CFAllocatorRef alloc = CFGetAllocator(relativeURL);
- CFURLPathStyle fsType = URL_PATH_TYPE(relativeURL);
- CFURLRef base = relativeURL->_base;
- CFStringRef newPath = _resolveFileSystemPaths(relativeURL->_string, base->_string, (base->_flags & IS_DIRECTORY) != 0, fsType, alloc);
- CFURLRef result = CFURLCreateWithFileSystemPath(alloc, newPath, fsType, (relativeURL->_flags & IS_DIRECTORY) != 0);
- CFRelease(newPath);
- return result;
-}
-
// Caller must release the returned string
static CFStringRef _resolveFileSystemPaths(CFStringRef relativePath, CFStringRef basePath, Boolean baseIsDir, CFURLPathStyle fsType, CFAllocatorRef alloc) {
CFIndex baseLen = CFStringGetLength(basePath);
CFIndex relLen = CFStringGetLength(relativePath);
- UniChar pathDelimiter = PATH_DELIM_FOR_TYPE(fsType);
+ UniChar pathDelimiter = '/';
UniChar *buf = (UniChar *)CFAllocatorAllocate(alloc, sizeof(UniChar)*(relLen + baseLen + 2), 0);
CFStringGetCharacters(basePath, CFRangeMake(0, baseLen), buf);
if (baseIsDir) {
CFIndex len;
CFURLRef baseURL, result;
- CFAssert2(fsType == kCFURLPOSIXPathStyle || fsType == kCFURLHFSPathStyle || fsType == kCFURLWindowsPathStyle || ASSERT_CHECK_PATHSTYLE(fsType), __kCFLogAssertion, "%s(): encountered unknown path style %d", __PRETTY_FUNCTION__, fsType);
+ CFAssert2(fsType == kCFURLPOSIXPathStyle || fsType == kCFURLHFSPathStyle || fsType == kCFURLWindowsPathStyle, __kCFLogAssertion, "%s(): encountered unknown path style %d", __PRETTY_FUNCTION__, fsType);
CFAssert1(filePath != NULL, __kCFLogAssertion, "%s(): NULL filePath argument not permitted", __PRETTY_FUNCTION__);
CFIndex len;
CFAssert1(filePath != NULL, __kCFLogAssertion, "%s(): NULL path string not permitted", __PRETTY_FUNCTION__);
- CFAssert2(fsType == kCFURLPOSIXPathStyle || fsType == kCFURLHFSPathStyle || fsType == kCFURLWindowsPathStyle || ASSERT_CHECK_PATHSTYLE(fsType), __kCFLogAssertion, "%s(): encountered unknown path style %d", __PRETTY_FUNCTION__, fsType);
+ CFAssert2(fsType == kCFURLPOSIXPathStyle || fsType == kCFURLHFSPathStyle || fsType == kCFURLWindowsPathStyle, __kCFLogAssertion, "%s(): encountered unknown path style %d", __PRETTY_FUNCTION__, fsType);
len = CFStringGetLength(filePath);
/* Absolute path under Win32 can begin with "\\"
* (Sergey Zubarev)
*/
- if (!isAbsolute)
- isAbsolute = (len > 2 && CFStringGetCharacterAtIndex(filePath, 0) == '\\' && CFStringGetCharacterAtIndex(filePath, 1) == '\\');
+ if (!isAbsolute)
+ isAbsolute = (len > 2 && CFStringGetCharacterAtIndex(filePath, 0) == '\\' && CFStringGetCharacterAtIndex(filePath, 1) == '\\');
pathDelim = '\\';
break;
case kCFURLHFSPathStyle:
CFStringAppend(newString, CFSTR("./"));
CFStringAppend(newString, url->_string);
CFRelease(url->_string);
- ((struct __CFURL *)url)->_string = newString;
+ ((struct __CFURL *)url)->_string = CFStringCreateCopy(allocator, newString);
+ CFRelease(newString);
}
}
return url;
static Boolean _pathHasFileIDPrefix( CFStringRef path )
{
// path is not NULL, path has prefix "/.file/" and has at least one character following the prefix.
+#ifdef __CONSTANT_STRINGS__
+ static const
+#endif
CFStringRef fileIDPrefix = CFSTR( "/" FILE_ID_PREFIX "/" );
return path && CFStringHasPrefix( path, fileIDPrefix ) && CFStringGetLength( path ) > CFStringGetLength( fileIDPrefix );
}
-
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
static Boolean _pathHasFileIDOnly( CFStringRef path )
{
// Is file ID rooted and contains no additonal path segments
CFRange slashRange;
return _pathHasFileIDPrefix( path ) && ( !CFStringFindWithOptions( path, CFSTR("/"), CFRangeMake( sizeof(FILE_ID_PREFIX) + 1, CFStringGetLength( path ) - sizeof(FILE_ID_PREFIX) - 1), 0, &slashRange ) || slashRange.location == CFStringGetLength( path ) - 1 );
}
-
+#endif
CF_EXPORT CFStringRef CFURLCopyFileSystemPath(CFURLRef anURL, CFURLPathStyle pathStyle) {
- CFAssert2(pathStyle == kCFURLPOSIXPathStyle || pathStyle == kCFURLHFSPathStyle || pathStyle == kCFURLWindowsPathStyle || ASSERT_CHECK_PATHSTYLE(pathStyle), __kCFLogAssertion, "%s(): Encountered unknown path style %d", __PRETTY_FUNCTION__, pathStyle);
+ CFAssert2(pathStyle == kCFURLPOSIXPathStyle || pathStyle == kCFURLHFSPathStyle || pathStyle == kCFURLWindowsPathStyle, __kCFLogAssertion, "%s(): Encountered unknown path style %d", __PRETTY_FUNCTION__, pathStyle);
- return CFURLCreateStringWithFileSystemPath(CFGetAllocator(anURL), anURL, pathStyle, false);
+ CFStringRef result;
+
+ result = CFURLCreateStringWithFileSystemPath(CFGetAllocator(anURL), anURL, pathStyle, false);
+ return ( result );
}
if (!CF_IS_OBJC(__kCFURLTypeID, anURL)) {
// We can grope the ivars
- CFURLPathStyle myType = URL_PATH_TYPE(anURL);
- if (myType == fsType) {
- relPath = (CFStringRef)CFRetain(anURL->_string);
- } else if (fsType == kCFURLPOSIXPathStyle && myType == FULL_URL_REPRESENTATION) {
- if (!(anURL->_flags & IS_PARSED)) {
- _parseComponentsOfURL(anURL);
- }
+ if (fsType == kCFURLPOSIXPathStyle) {
if (anURL->_flags & POSIX_AND_URL_PATHS_MATCH) {
relPath = _retainedComponentString(anURL, HAS_PATH, true, true);
}
if (relPath == NULL) {
CFStringRef urlPath = CFURLCopyPath(anURL);
- CFStringEncoding enc = (anURL->_flags & IS_OLD_UTF8_STYLE) ? kCFStringEncodingUTF8 : anURL->_encoding;
+ CFStringEncoding enc = anURL->_encoding;
if (urlPath) {
switch (fsType) {
case kCFURLPOSIXPathStyle:
// and do a linked-on-or-later check so we don't break third parties.
// See <rdar://problem/4003028> Converting volume name from POSIX to HFS form fails and
// <rdar://problem/4018895> CF needs to back out 4003028 for icky details.
- if ( relPath && CFURLHasDirectoryPath(anURL) && CFStringGetLength(relPath) > 1 && CFStringGetCharacterAtIndex(relPath, CFStringGetLength(relPath)-1) == PATH_DELIM_FOR_TYPE(fsType)) {
+ if ( relPath && CFURLHasDirectoryPath(anURL) && CFStringGetLength(relPath) > 1 && CFStringGetCharacterAtIndex(relPath, CFStringGetLength(relPath)-1) == '/') {
CFStringRef tmp = CFStringCreateWithSubstring(allocator, relPath, CFRangeMake(0, CFStringGetLength(relPath)-1));
CFRelease(relPath);
relPath = tmp;
}
- // Note that !resolveAgainstBase implies !base
- if (!basePath || !relPath) {
+ if ( relPath ) {
if ( basePath ) {
+ // we have both basePath and relPath -- resolve them
+ CFStringRef result = _resolveFileSystemPaths(relPath, basePath, CFURLHasDirectoryPath(base), fsType, allocator);
CFRelease(basePath);
+ CFRelease(relPath);
+ return result;
}
- return relPath;
- } else {
- CFStringRef result = _resolveFileSystemPaths(relPath, basePath, CFURLHasDirectoryPath(base), fsType, allocator);
- CFRelease(basePath);
- CFRelease(relPath);
- return result;
+ else {
+ // we only have the relPath -- return it
+ return relPath;
+ }
+ }
+ else if ( basePath ) {
+ // we only have the basePath --- return it
+ return basePath;
+ }
+ else {
+ // we have nothing to return
+ return NULL;
}
}
Boolean CFURLGetFileSystemRepresentation(CFURLRef url, Boolean resolveAgainstBase, uint8_t *buffer, CFIndex bufLen) {
- CFStringRef path;
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || 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 ( !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);
+ }
+ }
+ }
+ // else fall back to slower way.
path = CFURLCreateStringWithFileSystemPath(alloc, url, kCFURLPOSIXPathStyle, resolveAgainstBase);
if (path) {
Boolean convResult = _CFStringGetFileSystemRepresentation(path, buffer, bufLen);
return true;
}
}
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
return 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));
+ }
+
+ 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);
+ }
+ }
+ else {
+ result = NULL;
+ }
+
+ if ( addedPercentEncoding ) {
+ *addedPercentEncoding = addedPercent;
+ }
+
+ return ( result );
+}
+
CFURLRef CFURLCreateFromFileSystemRepresentation(CFAllocatorRef allocator, const uint8_t *buffer, CFIndex bufLen, Boolean isDirectory) {
- CFStringRef path = _createPathFromFileSystemRepresentation(allocator, buffer, bufLen, isDirectory);
- CFURLRef newURL;
- if (!path) return NULL;
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+ 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;
+ }
+ }
#elif DEPLOYMENT_TARGET_WINDOWS
+ CFStringRef path = _createPathFromFileSystemRepresentation(allocator, buffer, bufLen, isDirectory);
+ if ( path ) {
newURL = CFURLCreateWithFileSystemPath(allocator, path, kCFURLWindowsPathStyle, isDirectory);
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
+ CFRelease(path);
+ }
+ else {
+ newURL = NULL;
+ }
#endif
- CFRelease(path);
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;
+ 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);
-#else
-#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
CFRelease(path);
return newURL;
// Assumes url is a CFURL (not an Obj-C NSURL)
static CFRange _rangeOfLastPathComponent(CFURLRef url) {
- UInt32 pathType = URL_PATH_TYPE(url);
CFRange pathRg, componentRg;
- if (pathType == FULL_URL_REPRESENTATION) {
- if (!(url->_flags & IS_PARSED)) _parseComponentsOfURL(url);
- pathRg = _rangeForComponent(url->_flags, url->ranges, HAS_PATH);
- } else {
- pathRg = CFRangeMake(0, CFStringGetLength(url->_string));
- }
+ pathRg = _rangeForComponent(url->_flags, url->_ranges, HAS_PATH);
if (pathRg.location == kCFNotFound || pathRg.length == 0) {
// No path
return pathRg;
}
- if (CFStringGetCharacterAtIndex(url->_string, pathRg.location + pathRg.length - 1) == PATH_DELIM_FOR_TYPE(pathType)) {
+ if (CFStringGetCharacterAtIndex(url->_string, pathRg.location + pathRg.length - 1) == '/') {
pathRg.length --;
if (pathRg.length == 0) {
pathRg.length ++;
return pathRg;
}
}
- if (CFStringFindWithOptions(url->_string, PATH_DELIM_AS_STRING_FOR_TYPE(pathType), pathRg, kCFCompareBackwards, &componentRg)) {
+ if (CFStringFindWithOptions(url->_string, CFSTR("/"), pathRg, kCFCompareBackwards, &componentRg)) {
componentRg.location ++;
componentRg.length = pathRg.location + pathRg.length - componentRg.location;
} else {
CFStringRef result;
if (CF_IS_OBJC(__kCFURLTypeID, url)) {
- CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
+ CFStringRef path = CFURLCreateStringWithFileSystemPath(CFGetAllocator(url), url, kCFURLPOSIXPathStyle, false);
CFIndex length;
CFRange rg, compRg;
if (!path) return NULL;
CFRelease(path);
}
} else {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
Boolean filePathURLCreated = false;
-
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( _CFURLIsFileReferenceURL(url) ) {
// use a file path URL or fail
CFURLRef filePathURL = CFURLCreateFilePathURL(CFGetAllocator(url), url, NULL);
CFRange rg = _rangeOfLastPathComponent(url);
if (rg.location == kCFNotFound || rg.length == 0) {
// No path
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( filePathURLCreated ) {
CFRelease(url);
}
-#endif
return (CFStringRef)CFRetain(CFSTR(""));
}
- if (rg.length == 1 && CFStringGetCharacterAtIndex(url->_string, rg.location) == PATH_DELIM_FOR_TYPE(URL_PATH_TYPE(url))) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+ if (rg.length == 1 && CFStringGetCharacterAtIndex(url->_string, rg.location) == '/') {
if ( filePathURLCreated ) {
CFRelease(url);
}
-#endif
return (CFStringRef)CFRetain(CFSTR("/"));
}
result = CFStringCreateWithSubstring(CFGetAllocator(url), url->_string, rg);
- if (URL_PATH_TYPE(url) == FULL_URL_REPRESENTATION && !(url->_flags & POSIX_AND_URL_PATHS_MATCH)) {
+ if (!(url->_flags & POSIX_AND_URL_PATHS_MATCH)) {
CFStringRef tmp;
- if (url->_flags & IS_OLD_UTF8_STYLE || url->_encoding == kCFStringEncodingUTF8) {
+ if (url->_encoding == kCFStringEncodingUTF8) {
tmp = CFURLCreateStringByReplacingPercentEscapes(CFGetAllocator(url), result, CFSTR(""));
} else {
tmp = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(CFGetAllocator(url), result, CFSTR(""), url->_encoding);
CFRelease(result);
result = tmp;
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( filePathURLCreated ) {
CFRelease(url);
}
-#endif
}
return result;
}
}
CFURLRef CFURLCreateCopyAppendingPathComponent(CFAllocatorRef allocator, CFURLRef url, CFStringRef pathComponent, Boolean isDirectory) {
- UInt32 fsType;
CFURLRef result;
url = _CFURLFromNSURL(url);
__CFGenericValidateType(url, __kCFURLTypeID);
CFAssert1(pathComponent != NULL, __kCFLogAssertion, "%s(): Cannot be called with a NULL component to append", __PRETTY_FUNCTION__);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
Boolean filePathURLCreated = false;
-
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( _CFURLIsFileReferenceURL(url) ) {
// use a file path URL if possible (only because this is appending a path component)
CFURLRef filePathURL = CFURLCreateFilePathURL(allocator, url, NULL);
}
#endif
- fsType = URL_PATH_TYPE(url);
- if (fsType != FULL_URL_REPRESENTATION && CFStringFindWithOptions(pathComponent, PATH_DELIM_AS_STRING_FOR_TYPE(fsType), CFRangeMake(0, CFStringGetLength(pathComponent)), 0, NULL)) {
- // Must convert to full representation, and then work with it
- fsType = FULL_URL_REPRESENTATION;
- _convertToURLRepresentation((struct __CFURL *)url);
+ CFMutableStringRef newString;
+ CFStringRef newComp;
+ CFRange pathRg;
+ if (!(url->_flags & HAS_PATH)) {
+ result = NULL;
}
-
- if (fsType == FULL_URL_REPRESENTATION) {
- CFMutableStringRef newString;
- CFStringRef newComp;
- CFRange pathRg;
- if (!(url->_flags & IS_PARSED)) _parseComponentsOfURL(url);
- if (!(url->_flags & HAS_PATH)) {
- result = NULL;
- }
- else {
- newString = CFStringCreateMutableCopy(allocator, 0, url->_string);
- newComp = CFURLCreateStringByAddingPercentEscapes(allocator, pathComponent, NULL, CFSTR(";?"), (url->_flags & IS_OLD_UTF8_STYLE) ? kCFStringEncodingUTF8 : url->_encoding);
- pathRg = _rangeForComponent(url->_flags, url->ranges, HAS_PATH);
- if (!pathRg.length || CFStringGetCharacterAtIndex(url->_string, pathRg.location + pathRg.length - 1) != '/') {
- CFStringInsert(newString, pathRg.location + pathRg.length, CFSTR("/"));
- pathRg.length ++;
- }
- CFStringInsert(newString, pathRg.location + pathRg.length, newComp);
- if (isDirectory) {
- CFStringInsert(newString, pathRg.location + pathRg.length + CFStringGetLength(newComp), CFSTR("/"));
- }
- CFRelease(newComp);
- result = _CFURLCreateWithArbitraryString(allocator, newString, url->_base);
- CFRelease(newString);
+ else {
+ newString = CFStringCreateMutableCopy(allocator, 0, url->_string);
+ newComp = CFURLCreateStringByAddingPercentEscapes(allocator, pathComponent, NULL, CFSTR(";?"), url->_encoding);
+ pathRg = _rangeForComponent(url->_flags, url->_ranges, HAS_PATH);
+ if ( (!pathRg.length || CFStringGetCharacterAtIndex(url->_string, pathRg.location + pathRg.length - 1) != '/') && (CFStringGetCharacterAtIndex(newComp, 0) != '/') ) {
+ CFStringInsert(newString, pathRg.location + pathRg.length, CFSTR("/"));
+ pathRg.length ++;
}
- } else {
- UniChar pathDelim = PATH_DELIM_FOR_TYPE(fsType);
- CFStringRef newString;
- if (CFStringGetCharacterAtIndex(url->_string, CFStringGetLength(url->_string) - 1) != pathDelim) {
- if (isDirectory) {
- newString = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@%c%@%c"), url->_string, pathDelim, pathComponent, pathDelim);
- } else {
- newString = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@%c%@"), url->_string, pathDelim, pathComponent);
- }
- } else {
- if (isDirectory) {
- newString = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@%@%c"), url->_string, pathComponent, pathDelim);
- } else {
- newString = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@%@"), url->_string, pathComponent);
- }
+ CFStringInsert(newString, pathRg.location + pathRg.length, newComp);
+ if (isDirectory) {
+ CFStringInsert(newString, pathRg.location + pathRg.length + CFStringGetLength(newComp), CFSTR("/"));
}
- result = CFURLCreateWithFileSystemPathRelativeToBase(allocator, newString, fsType, isDirectory, url->_base);
+ CFRelease(newComp);
+ result = _CFURLCreateWithArbitraryString(allocator, newString, url->_base);
CFRelease(newString);
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( filePathURLCreated ) {
CFRelease(url);
}
-#endif
return result;
}
CFMutableStringRef newString;
CFRange lastCompRg, pathRg;
Boolean appendDotDot = false;
- UInt32 fsType;
url = _CFURLFromNSURL(url);
CFAssert1(url != NULL, __kCFLogAssertion, "%s(): NULL argument not allowed", __PRETTY_FUNCTION__);
__CFGenericValidateType(url, __kCFURLTypeID);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
Boolean filePathURLCreated = false;
-
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( _CFURLIsFileReferenceURL(url) ) {
// use a file path URL or fail
CFURLRef filePathURL = CFURLCreateFilePathURL(allocator, url, NULL);
}
#endif
- fsType = URL_PATH_TYPE(url);
- if (fsType == FULL_URL_REPRESENTATION) {
- if (!(url->_flags & IS_PARSED)) _parseComponentsOfURL(url);
- if (!(url->_flags & HAS_PATH)) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
- if ( filePathURLCreated ) {
- CFRelease(url);
- }
-#endif
- return NULL;
+ if (!(url->_flags & HAS_PATH)) {
+ if ( filePathURLCreated ) {
+ CFRelease(url);
}
- pathRg = _rangeForComponent(url->_flags, url->ranges, HAS_PATH);
- } else {
- pathRg = CFRangeMake(0, CFStringGetLength(url->_string));
+ return NULL;
}
+ pathRg = _rangeForComponent(url->_flags, url->_ranges, HAS_PATH);
lastCompRg = _rangeOfLastPathComponent(url);
if (lastCompRg.length == 0) {
appendDotDot = true;
} else if (lastCompRg.length == 1) {
UniChar ch = CFStringGetCharacterAtIndex(url->_string, lastCompRg.location);
- if (ch == '.' || ch == PATH_DELIM_FOR_TYPE(fsType)) {
+ if (ch == '.' || ch == '/') {
appendDotDot = true;
}
} else if (lastCompRg.length == 2 && CFStringGetCharacterAtIndex(url->_string, lastCompRg.location) == '.' && CFStringGetCharacterAtIndex(url->_string, lastCompRg.location+1) == '.') {
newString = CFStringCreateMutableCopy(allocator, 0, url->_string);
if (appendDotDot) {
CFIndex delta = 0;
- if (pathRg.length > 0 && CFStringGetCharacterAtIndex(url->_string, pathRg.location + pathRg.length - 1) != PATH_DELIM_FOR_TYPE(fsType)) {
- CFStringInsert(newString, pathRg.location + pathRg.length, PATH_DELIM_AS_STRING_FOR_TYPE(fsType));
+ if (pathRg.length > 0 && CFStringGetCharacterAtIndex(url->_string, pathRg.location + pathRg.length - 1) != '/') {
+ CFStringInsert(newString, pathRg.location + pathRg.length, CFSTR("/"));
delta ++;
}
CFStringInsert(newString, pathRg.location + pathRg.length + delta, CFSTR(".."));
delta += 2;
- CFStringInsert(newString, pathRg.location + pathRg.length + delta, PATH_DELIM_AS_STRING_FOR_TYPE(fsType));
+ CFStringInsert(newString, pathRg.location + pathRg.length + delta, CFSTR("/"));
delta ++;
// We know we have "/../" at the end of the path; we wish to know if that's immediately preceded by "/." (but that "/." doesn't start the string), in which case we want to delete the "/.".
if (pathRg.length + delta > 4 && CFStringGetCharacterAtIndex(newString, pathRg.location + pathRg.length + delta - 5) == '.') {
- if (pathRg.length+delta > 7 && CFStringGetCharacterAtIndex(newString, pathRg.location + pathRg.length + delta - 6) == PATH_DELIM_FOR_TYPE(fsType)) {
+ if (pathRg.length+delta > 7 && CFStringGetCharacterAtIndex(newString, pathRg.location + pathRg.length + delta - 6) == '/') {
CFStringDelete(newString, CFRangeMake(pathRg.location + pathRg.length + delta - 6, 2));
} else if (pathRg.length+delta == 5) {
CFStringDelete(newString, CFRangeMake(pathRg.location + pathRg.length + delta - 5, 2));
}
} else if (lastCompRg.location == pathRg.location) {
CFStringReplace(newString, pathRg, CFSTR("."));
- CFStringInsert(newString, 1, PATH_DELIM_AS_STRING_FOR_TYPE(fsType));
+ CFStringInsert(newString, 1, CFSTR("/"));
} else {
CFStringDelete(newString, CFRangeMake(lastCompRg.location, pathRg.location + pathRg.length - lastCompRg.location));
}
- if (fsType == FULL_URL_REPRESENTATION) {
- result = _CFURLCreateWithArbitraryString(allocator, newString, url->_base);
- } else {
- result = CFURLCreateWithFileSystemPathRelativeToBase(allocator, newString, fsType, true, url->_base);
- }
+ result = _CFURLCreateWithArbitraryString(allocator, newString, url->_base);
CFRelease(newString);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( filePathURLCreated ) {
CFRelease(url);
}
-#endif
return result;
}
CFMutableStringRef newString;
CFURLRef result;
CFRange rg;
- CFURLPathStyle fsType;
CFAssert1(url != NULL && extension != NULL, __kCFLogAssertion, "%s(): NULL argument not allowed", __PRETTY_FUNCTION__);
url = _CFURLFromNSURL(url);
__CFGenericValidateType(url, __kCFURLTypeID);
__CFGenericValidateType(extension, CFStringGetTypeID());
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
Boolean filePathURLCreated = false;
-
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( _CFURLIsFileReferenceURL(url) ) {
// use a file path URL or fail
CFURLRef filePathURL = CFURLCreateFilePathURL(allocator, url, NULL);
rg = _rangeOfLastPathComponent(url);
if (rg.location < 0) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( filePathURLCreated ) {
CFRelease(url);
}
-#endif
return NULL; // No path
}
- fsType = URL_PATH_TYPE(url);
- if (fsType != FULL_URL_REPRESENTATION && CFStringFindWithOptions(extension, PATH_DELIM_AS_STRING_FOR_TYPE(fsType), CFRangeMake(0, CFStringGetLength(extension)), 0, NULL)) {
- _convertToURLRepresentation((struct __CFURL *)url);
- fsType = FULL_URL_REPRESENTATION;
- rg = _rangeOfLastPathComponent(url);
- }
newString = CFStringCreateMutableCopy(allocator, 0, url->_string);
CFStringInsert(newString, rg.location + rg.length, CFSTR("."));
- if (fsType == FULL_URL_REPRESENTATION) {
- CFStringRef newExt = CFURLCreateStringByAddingPercentEscapes(allocator, extension, NULL, CFSTR(";?/"), (url->_flags & IS_OLD_UTF8_STYLE) ? kCFStringEncodingUTF8 : url->_encoding);
- CFStringInsert(newString, rg.location + rg.length + 1, newExt);
- CFRelease(newExt);
- result = _CFURLCreateWithArbitraryString(allocator, newString, url->_base);
- } else {
- CFStringInsert(newString, rg.location + rg.length + 1, extension);
- result = CFURLCreateWithFileSystemPathRelativeToBase(allocator, newString, fsType, (url->_flags & IS_DIRECTORY) != 0 ? true : false, url->_base);
- }
+ CFStringRef newExt = CFURLCreateStringByAddingPercentEscapes(allocator, extension, NULL, CFSTR(";?/"), url->_encoding);
+ CFStringInsert(newString, rg.location + rg.length + 1, newExt);
+ CFRelease(newExt);
+ result = _CFURLCreateWithArbitraryString(allocator, newString, url->_base);
CFRelease(newString);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( filePathURLCreated ) {
CFRelease(url);
}
-#endif
return result;
}
url = _CFURLFromNSURL(url);
__CFGenericValidateType(url, __kCFURLTypeID);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
Boolean filePathURLCreated = false;
-
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( _CFURLIsFileReferenceURL(url) ) {
// use a file path URL or fail
CFURLRef filePathURL = CFURLCreateFilePathURL(allocator, url, NULL);
CFMutableStringRef newString = CFStringCreateMutableCopy(allocator, 0, url->_string);
dotRg.length = rg.location + rg.length - dotRg.location;
CFStringDelete(newString, dotRg);
- if (URL_PATH_TYPE(url) == FULL_URL_REPRESENTATION) {
- result = _CFURLCreateWithArbitraryString(allocator, newString, url->_base);
- } else {
- result = CFURLCreateWithFileSystemPathRelativeToBase(allocator, newString, URL_PATH_TYPE(url), (url->_flags & IS_DIRECTORY) != 0 ? true : false, url->_base);
- }
+ result = _CFURLCreateWithArbitraryString(allocator, newString, url->_base);
CFRelease(newString);
} else {
result = (CFURLRef)CFRetain(url);
}
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if ( filePathURLCreated ) {
CFRelease(url);
}
-#endif
return result;
}
}
return newComponents;
}
+
+typedef CFStringRef (*StringTransformation)(CFAllocatorRef, CFStringRef, CFIndex);
+static CFArrayRef copyStringArrayWithTransformation(CFArrayRef array, StringTransformation transformation) {
+ CFAllocatorRef alloc = CFGetAllocator(array);
+ CFMutableArrayRef mArray = NULL;
+ CFIndex i, c = CFArrayGetCount(array);
+ for (i = 0; i < c; i ++) {
+ CFStringRef origComp = (CFStringRef)CFArrayGetValueAtIndex(array, i);
+ CFStringRef unescapedComp = transformation(alloc, origComp, i);
+ if (!unescapedComp) {
+ break;
+ }
+ if (unescapedComp != origComp) {
+ if (!mArray) {
+ mArray = CFArrayCreateMutableCopy(alloc, c, array);
+ }
+ CFArraySetValueAtIndex(mArray, i, unescapedComp);
+ }
+ CFRelease(unescapedComp);
+ }
+ if (i != c) {
+ if (mArray) CFRelease(mArray);
+ return NULL;
+ } else if (mArray) {
+ return mArray;
+ } else {
+ CFRetain(array);
+ return array;
+ }
+}
+
+static CFStringRef escapePathComponent(CFAllocatorRef alloc, CFStringRef origComponent, CFIndex componentIndex) {
+ return CFURLCreateStringByAddingPercentEscapes(alloc, origComponent, NULL, CFSTR(";?/"), kCFStringEncodingUTF8);
+}
+
static CFStringRef HFSPathToURLPath(CFStringRef path, CFAllocatorRef alloc, Boolean isDir) {
CFArrayRef components = HFSPathToURLComponents(path, alloc, isDir);
CFArrayRef newComponents = components ? copyStringArrayWithTransformation(components, escapePathComponent) : NULL;
vals[0] = CFNumberCreate(alloc, kCFNumberSInt32Type, &urlType);
vals[1] = CFURLGetString(url);
} else {
- SInt32 urlType = URL_PATH_TYPE(url);
+ SInt32 urlType = FULL_URL_REPRESENTATION;
vals[0] = CFNumberCreate(alloc, kCFNumberSInt32Type, &urlType);
if (url->_flags & IS_DIRECTORY) {
- if (CFStringGetCharacterAtIndex(url->_string, CFStringGetLength(url->_string) - 1) == PATH_DELIM_FOR_TYPE(urlType)) {
+ if (CFStringGetCharacterAtIndex(url->_string, CFStringGetLength(url->_string) - 1) == '/') {
vals[1] = CFRetain(url->_string);
} else {
- vals[1] = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@%c"), url->_string, PATH_DELIM_FOR_TYPE(urlType));
+ vals[1] = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@%c"), url->_string, '/');
}
} else {
- if (CFStringGetCharacterAtIndex(url->_string, CFStringGetLength(url->_string) - 1) != PATH_DELIM_FOR_TYPE(urlType)) {
+ if (CFStringGetCharacterAtIndex(url->_string, CFStringGetLength(url->_string) - 1) != '/') {
vals[1] = CFRetain(url->_string);
} else {
vals[1] = CFStringCreateWithSubstring(alloc, url->_string, CFRangeMake(0, CFStringGetLength(url->_string) - 1));
vals[2] = CFNumberCreate(alloc, kCFNumberSInt32Type, &urlType);
vals[3] = CFURLGetString(base);
} else {
- SInt32 urlType = URL_PATH_TYPE(base);
+ SInt32 urlType = FULL_URL_REPRESENTATION;
vals[2] = CFNumberCreate(alloc, kCFNumberSInt32Type, &urlType);
if (base->_flags & IS_DIRECTORY) {
- if (CFStringGetCharacterAtIndex(base->_string, CFStringGetLength(base->_string) - 1) == PATH_DELIM_FOR_TYPE(urlType)) {
+ if (CFStringGetCharacterAtIndex(base->_string, CFStringGetLength(base->_string) - 1) == '/') {
vals[3] = CFRetain(base->_string);
} else {
- vals[3] = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@%c"), base->_string, PATH_DELIM_FOR_TYPE(urlType));
+ vals[3] = CFStringCreateWithFormat(alloc, NULL, CFSTR("%@%c"), base->_string, '/');
}
} else {
- if (CFStringGetCharacterAtIndex(base->_string, CFStringGetLength(base->_string) - 1) != PATH_DELIM_FOR_TYPE(urlType)) {
+ if (CFStringGetCharacterAtIndex(base->_string, CFStringGetLength(base->_string) - 1) != '/') {
vals[3] = CFRetain(base->_string);
} else {
vals[3] = CFStringCreateWithSubstring(alloc, base->_string, CFRangeMake(0, CFStringGetLength(base->_string) - 1));
if (baseType == FULL_URL_REPRESENTATION) {
baseURL = _CFURLCreateWithArbitraryString(alloc, baseString, NULL);
} else {
- baseURL = CFURLCreateWithFileSystemPathRelativeToBase(alloc, baseString, (CFURLPathStyle)baseType, CFStringGetCharacterAtIndex(baseString, CFStringGetLength(baseString)-1) == PATH_DELIM_FOR_TYPE(baseType), NULL);
+ baseURL = CFURLCreateWithFileSystemPathRelativeToBase(alloc, baseString, (CFURLPathStyle)baseType, CFStringGetCharacterAtIndex(baseString, CFStringGetLength(baseString)-1) == '/', NULL);
}
}
if (urlType == FULL_URL_REPRESENTATION) {
url = _CFURLCreateWithArbitraryString(alloc, string, baseURL);
} else {
- url = CFURLCreateWithFileSystemPathRelativeToBase(alloc, string, (CFURLPathStyle)urlType, CFStringGetCharacterAtIndex(string, CFStringGetLength(string)-1) == PATH_DELIM_FOR_TYPE(urlType), baseURL);
+ url = CFURLCreateWithFileSystemPathRelativeToBase(alloc, string, (CFURLPathStyle)urlType, CFStringGetCharacterAtIndex(string, CFStringGetLength(string)-1) == '/', baseURL);
}
if (baseURL) CFRelease(baseURL);
return url;
Boolean _CFURLIsFileReferenceURL(CFURLRef url)
{
// returns TRUE if url is is a file URL whose path starts with a file ID reference
- if ( url->_base ) {
- return _CFURLIsFileReferenceURL( url->_base );
+ Boolean result = false;
+ CFURLRef baseURL = CFURLGetBaseURL(url);
+ if ( baseURL ) {
+ result = _CFURLIsFileReferenceURL(baseURL);
}
- if (URL_PATH_TYPE(url) == kCFURLFileReferencePathStyle) {
- return true;
- } else if (URL_PATH_TYPE(url) == FULL_URL_REPRESENTATION ) {
- if (!(url->_flags & IS_PARSED)) {
- _parseComponentsOfURL(url);
- }
- return ((url->_flags & HAS_FILE_SCHEME) && (url->_flags & PATH_HAS_FILE_ID));
+ 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));
+ }
}
- // Otherwise, the path type is some other non-ID path type
- return false;
+ return ( result );
}
-Boolean _CFURLIsFileURL(CFURLRef url)
+static Boolean _CFURLHasFileURLScheme(CFURLRef url, Boolean *hasScheme)
{
- if ( url->_base ) {
- return _CFURLIsFileURL( url->_base );
+ Boolean result;
+ CFURLRef baseURL = CFURLGetBaseURL(url);
+
+ if ( baseURL ) {
+ result = _CFURLHasFileURLScheme(baseURL, hasScheme);
}
- if (URL_PATH_TYPE(url) != FULL_URL_REPRESENTATION) {
- return true;
- } else if (!(url->_flags & IS_PARSED)) {
- _parseComponentsOfURL(url);
+ else {
+ if ( CF_IS_OBJC(__kCFURLTypeID, url) ) {
+ CFStringRef scheme = CFURLCopyScheme(url);
+ if ( scheme ) {
+ if ( scheme == kCFURLFileScheme ) {
+ result = true;
+ }
+ else {
+ result = CFStringCompare(scheme, kCFURLFileScheme, kCFCompareCaseInsensitive) == kCFCompareEqualTo;
+ }
+ if ( hasScheme ) {
+ *hasScheme = true;
+ }
+ CFRelease(scheme);
+ }
+ else {
+ if ( hasScheme ) {
+ *hasScheme = false;
+ }
+ result = false;
+ }
+ }
+ else {
+ if ( hasScheme ) {
+ *hasScheme = (url->_flags & HAS_SCHEME) != 0;
+ }
+ result = (_getSchemeTypeFromFlags(url->_flags) == kHasFileScheme);
+ }
}
- return (url->_flags & HAS_FILE_SCHEME) != 0;
+ return ( result );
}
+Boolean _CFURLIsFileURL(CFURLRef url)
+{
+ Boolean result = _CFURLHasFileURLScheme(url, NULL);
+ return ( result );
+}
CFURLRef CFURLCreateFilePathURL(CFAllocatorRef alloc, CFURLRef url, CFErrorRef *error)
{
CFURLRef result = NULL;
- if (!_CFURLIsFileURL(url)) {
+ Boolean hasScheme;
+ if (!_CFURLHasFileURLScheme(url, &hasScheme)) {
+ if ( !hasScheme ) {
+ CFLog(kCFLogLevelWarning, CFSTR("CFURLCreateFilePathURL failed because it was passed this URL which has no scheme: %@"), url);
+ }
if ( error ) {
*error = CFErrorCreate( kCFAllocatorDefault, kCFErrorDomainCocoa, kCFURLReadUnsupportedSchemeError, NULL );
}
if ( CFURLGetBaseURL( url )) {
CFURLRef absURL = CFURLCopyAbsoluteURL( url );
- fsPath = CFURLCopyFileSystemPath( absURL, kCFURLPOSIXPathStyle );
+ fsPath = CFURLCreateStringWithFileSystemPath(CFGetAllocator(absURL), absURL, kCFURLPOSIXPathStyle, false);
netLoc = CFURLCopyNetLocation( absURL );
rSpec = CFURLCopyResourceSpecifier( absURL );
CFRelease( absURL );
} else {
- fsPath = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle );
+ fsPath = CFURLCreateStringWithFileSystemPath(CFGetAllocator(url), url, kCFURLPOSIXPathStyle, false);
netLoc = CFURLCopyNetLocation( url );
rSpec = CFURLCopyResourceSpecifier( url );
}
CFRelease( fsPath );
} else {
if ( error ) {
- // Would be better here to get an underlying error back from CFURLCopyFileSystemPath
+ // Would be better here to get an underlying error back from CFURLCreateStringWithFileSystemPath
*error = CFErrorCreate( kCFAllocatorDefault, kCFErrorDomainCocoa, kCFURLNoSuchResourceError, NULL );
}
result = NULL;
#endif
-CFURLRef CFURLCreateFileReferenceURL(CFAllocatorRef alloc, CFURLRef url, CFErrorRef *error) {
- return NULL;
-}
+
+CFURLRef CFURLCreateFileReferenceURL(CFAllocatorRef alloc, CFURLRef url, CFErrorRef *error) { return NULL; }
+
*/
/* CFURL.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFURL__)
#include <CoreFoundation/CFData.h>
#include <CoreFoundation/CFError.h>
#include <CoreFoundation/CFString.h>
-#include <CoreFoundation/CFNumber.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
-enum {
+typedef CF_ENUM(CFIndex, CFURLPathStyle) {
kCFURLPOSIXPathStyle = 0,
- kCFURLHFSPathStyle,
+ 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. */
kCFURLWindowsPathStyle
};
-typedef CFIndex CFURLPathStyle;
typedef const struct __CFURL * CFURLRef;
CF_EXPORT
CFIndex CFURLGetBytes(CFURLRef url, UInt8 *buffer, CFIndex bufferLength);
-enum {
+typedef CF_ENUM(CFIndex, CFURLComponentType) {
kCFURLComponentScheme = 1,
kCFURLComponentNetLocation = 2,
kCFURLComponentPath = 3,
kCFURLComponentQuery = 11,
kCFURLComponentFragment = 12
};
-typedef CFIndex CFURLComponentType;
/*
Gets the range of the requested component in the bytes of url, as
#if (TARGET_OS_MAC || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) || CF_BUILDING_CF || NSBUILDINGFOUNDATION
+CF_IMPLICIT_BRIDGING_DISABLED
-/* Returns a file reference URL, a path-idependent form of file URL. */
-/* Converts a file path URL if necessary. For non-file URLs, returns NULL. */
-/* Also returns NULL when the conversion fails because the target resource doesn't exist. */
-/* Optional output error: The error is set to a valid CFErrorRef when the function */
-/* result is NULL. A valid output error must be released by the caller. */
+/*
+ CFURLCreateFileReferenceURL
+
+ Returns a new file reference URL that refers to the same resource as a specified URL.
+
+ Parameters
+ allocator
+ The memory allocator for creating the new URL.
+ url
+ The file URL specifying the resource.
+ error
+ On output when the result is NULL, the error that occurred. This parameter is optional; if you do not wish the error returned, pass NULL here. The caller is responsible for releasing a valid output error.
+
+ Return Value
+ The new file reference URL, or NULL if an error occurs.
+
+ Discussion
+ File reference URLs use a URL path syntax that identifies a file system object by reference, not by path. This form of file URL remains valid when the file system path of the URL’s underlying resource changes. An error will occur if the url parameter is not a file URL. File reference URLs cannot be created to file system objects which do not exist or are not reachable. In some areas of the file system hierarchy, file reference URLs cannot be generated to the leaf node of the URL path. A file reference URL's path should never be persistently stored because is not valid across system restarts, and across remounts of volumes -- if you want to create a persistent reference to a file system object, use a bookmark (see CFURLCreateBookmarkData). If this function returns NULL, the optional error is populated. This function is currently applicable only to URLs for file system resources.
+ Symbol is present in iOS 4, but performs no operation.
+ */
CF_EXPORT
CFURLRef CFURLCreateFileReferenceURL(CFAllocatorRef allocator, CFURLRef url, CFErrorRef *error) CF_AVAILABLE(10_6, 4_0);
-/* Returns a file path URL, converting a file reference URL if necessary. */
-/* For non-file URLs, returns NULL. Also returns NULL when the conversion fails */
-/* because the target resource doesn't exist. */
-/* Optional output error: The error is set to a valid CFErrorRef when the function */
-/* result is NULL. A valid output error must be released by the caller. */
+/*
+ CFURLCreateFilePathURL
+
+ Returns a new file path URL that refers to the same resource as a specified URL.
+
+ Parameters
+ allocator
+ The memory allocator for creating the new URL.
+ url
+ The file URL specifying the resource.
+ error
+ On output when the result is NULL, the error that occurred. This parameter is optional; if you do not wish the error returned, pass NULL here. The caller is responsible for releasing a valid output error.
+
+ Return Value
+ The new file path URL, or NULL if an error occurs.
+
+ Discussion
+ File path URLs use a file system style path. An error will occur if the url parameter is not a file URL. A file reference URL's resource must exist and be reachable to be converted to a file path URL. If this function returns NULL, the optional error is populated. This function is currently applicable only to URLs for file system resources.
+ Symbol is present in iOS 4, but performs no operation.
+ */
CF_EXPORT
CFURLRef CFURLCreateFilePathURL(CFAllocatorRef allocator, CFURLRef url, CFErrorRef *error) CF_AVAILABLE(10_6, 4_0);
+CF_IMPLICIT_BRIDGING_ENABLED
#endif
#if (TARGET_OS_MAC || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) || CF_BUILDING_CF || NSBUILDINGFOUNDATION
+CF_IMPLICIT_BRIDGING_DISABLED
-/* The following APIs provide efficient access to resource properties. Properties
-are identified by keys, and values are represented as Core Foundation objects. The
-type of each value is fixed for each property, e.g. the modification date is a CFDateRef,
-the file size is a CFNumberRef.
+/* Resource access
-Values are fetched on-demand, synchronously, from the resource's backing store. They
-are cached and reused when fetched again through the same URL instance, until the
-client clears the value. The client has complete control over the cache lifetime.
+ The behavior of resource value caching is slightly different between the NSURL and CFURL API.
-Some resource property values can be changed, given sufficient access permission to the resource.
-When a resource property value is set, the change is written to backing store synchronously.
-*/
+ When the NSURL methods which get, set, or use cached resource values are used from the main thread, resource values cached by the URL (except those added as temporary properties) are invalidated the next time the main thread's run loop runs.
-/* Assigns the requested resource property value to the typeRefValuePtr output */
-/* argument. Returns true if the output value was set. Note that NULL is a valid output value. */
-/* The value is fetched synchronously from the resource backing store only if a value is not */
-/* already cached. The type of the output value type varies by property (see property key */
-/* definitions). Returns false if an error occurs. Optional output error: the error is set to */
-/* a valid CFErrorRef when the function returns false. A valid output error must be */
-/* released by the caller. */
+ The CFURL functions do not automatically clear any resource values cached by the URL. The client has complete control over the cache lifetime. If you are using CFURL API, you must use CFURLClearResourcePropertyCacheForKey or CFURLClearResourcePropertyCache to clear cached resource values.
+ */
+
+
+/*
+ CFURLCopyResourcePropertyForKey
+
+ Returns the resource value identified by a given resource key.
+
+ Parameters
+ url
+ The URL specifying the resource.
+ key
+ The resource key that identifies the resource property.
+ propertyValueTypeRefPtr
+ On output when the result is true, the resource value or NULL.
+ error
+ On output when the result is false, the error that occurred. This parameter is optional; if you do not wish the error returned, pass NULL here. The caller is responsible for releasing a valid output error.
+
+ Return Value
+ true if propertyValueTypeRefPtr is successfully populated; false if an error occurs.
+
+ Discussion
+ CFURLCopyResourcePropertyForKey first checks if the URL object already caches the resource value. If so, it returns the cached resource value to the caller. If not, then CFURLCopyResourcePropertyForKey synchronously obtains the resource value from the backing store, adds the resource value to the URL object's cache, and returns the resource value to the caller. The type of the resource value varies by resource property (see resource key definitions). If this function returns true and propertyValueTypeRefPtr is populated with NULL, it means the resource property is not available for the specified resource and no errors occurred when determining the resource property was not available. If this function returns false, the optional error is populated. This function is currently applicable only to URLs for file system resources.
+ Symbol is present in iOS 4, but performs no operation.
+ */
CF_EXPORT
Boolean CFURLCopyResourcePropertyForKey(CFURLRef url, CFStringRef key, void *propertyValueTypeRefPtr, CFErrorRef *error) CF_AVAILABLE(10_6, 4_0);
-/* Returns any number of resource property values as a dictionary of keyed values. */
-/* The requested values are specified as an array of keys to appear in */
-/* the result dictionary. Values are fetched synchronously from the resource backing store unless */
-/* already cached. The type of each value type varies (see key definitions, below). */
-/* Returns an empty dictionary if no values are found. Returns NULL when an error occurs. */
-/* Optional output error: the error is set to a valid CFErrorRef when the */
-/* function returns NULL. A valid output error must be released by the caller. */
+/*
+ CFURLCopyResourcePropertiesForKeys
+
+ Returns the resource values identified by specified array of resource keys.
+
+ Parameters
+ url
+ The URL specifying the resource.
+ keys
+ An array of resource keys that identify the resource properties.
+ error
+ On output when the result is NULL, the error that occurred. This parameter is optional; if you do not wish the error returned, pass NULL here. The caller is responsible for releasing a valid output error.
+
+ Return Value
+ A dictionary of resource values indexed by resource key; NULL if an error occurs.
+
+ Discussion
+ CFURLCopyResourcePropertiesForKeys first checks if the URL object already caches the resource values. If so, it returns the cached resource values to the caller. If not, then CFURLCopyResourcePropertyForKey synchronously obtains the resource values from the backing store, adds the resource values to the URL object's cache, and returns the resource values to the caller. The type of the resource values vary by property (see resource key definitions). If the result dictionary does not contain a resource value for one or more of the requested resource keys, it means those resource properties are not available for the specified resource and no errors occurred when determining those resource properties were not available. If this function returns NULL, the optional error is populated. This function is currently applicable only to URLs for file system resources.
+ Symbol is present in iOS 4, but performs no operation.
+ */
CF_EXPORT
CFDictionaryRef CFURLCopyResourcePropertiesForKeys(CFURLRef url, CFArrayRef keys, CFErrorRef *error) CF_AVAILABLE(10_6, 4_0);
-/* Changes a resource property value. Synchronously writes the value to the resource backing */
-/* store. The input value type must be a valid CFTypeRef, of the type required for the specified */
-/* key (see key definitions). Returns true upon success, false when an error occurs. */
-/* Optional output error: the error is set to a valid CFErrorRef when the function */
-/* returns false. A valid output error must be released by the caller. */
-/* Note that some values are read-only. Attempting to set a read-only property */
-/* results in an error. */
+/*
+ CFURLSetResourcePropertyForKey
+
+ Sets the resource value identified by a given resource key.
+
+ Parameters
+ url
+ The URL specifying the resource.
+ key
+ The resource key that identifies the resource property.
+ propertyValue
+ The resource value.
+ error
+ On output when the result is false, the error that occurred. This parameter is optional; if you do not wish the error returned, pass NULL here. The caller is responsible for releasing a valid output error.
+
+ Return Value
+ true if the attempt to set the resource value completed with no errors; otherwise, false.
+
+ Discussion
+ CFURLSetResourcePropertyForKey writes the new resource value out to the backing store. Attempts to set a read-only resource property or to set a resource property not supported by the resource are ignored and are not considered errors. If this function returns false, the optional error is populated. This function is currently applicable only to URLs for file system resources.
+ Symbol is present in iOS 4, but performs no operation.
+ */
CF_EXPORT
Boolean CFURLSetResourcePropertyForKey(CFURLRef url, CFStringRef key, CFTypeRef propertyValue, CFErrorRef *error) CF_AVAILABLE(10_6, 4_0);
-/* Changes any number of resource property values, specified as a dictionary of keyed values. */
-/* Synchronously writes values to the resource backing store. The input dictionary's value types must conform */
-/* to the type required for its key (see key definitions). Returns true when all values are set successfully, */
-/* and false if an error occurs. Optional output error: the error is set to a valid CFErrorRef when the function returns */
-/* false. A valid output error must be released by the caller. When an error occurs after some properties have been */
-/* successfully changed, the userInfo dictionary in the error contains an array of keys that */
-/* were not set with the dictionary key kCFURLKeysOfUnsetValuesKey. */
-/* Note that some values are read-only. Attempting to set a read-only value results in an error. */
+/*
+ CFURLSetResourcePropertiesForKeys
+
+ Sets any number of resource values of a URL's resource.
+
+ Parameters
+ url
+ The URL specifying the resource.
+ keyedPropertyValues
+ A dictionary of resource values indexed by resource keys.
+ error
+ On output when the result is false, the error that occurred. This parameter is optional; if you do not wish the error returned, pass NULL here. The caller is responsible for releasing a valid output error.
+
+ Return Value
+ true if the attempt to set the resource values completed with no errors; otherwise, false.
+
+ Discussion
+ CFURLSetResourcePropertiesForKeys writes the new resource values out to the backing store. Attempts to set read-only resource properties or to set resource properties not supported by the resource are ignored and are not considered errors. If an error occurs after some resource properties have been successfully changed, the userInfo dictionary in the returned error contains an array of resource keys that were not set with the key kCFURLKeysOfUnsetValuesKey. The order in which the resource values are set is not defined. If you need to guarantee the order resource values are set, you should make multiple requests to CFURLSetResourcePropertiesForKeys or CFURLSetResourcePropertyForKey to guarantee the order. If this function returns false, the optional error is populated. This function is currently applicable only to URLs for file system resources.
+ Symbol is present in iOS 4, but performs no operation.
+ */
CF_EXPORT
Boolean CFURLSetResourcePropertiesForKeys(CFURLRef url, CFDictionaryRef keyedPropertyValues, CFErrorRef *error) CF_AVAILABLE(10_6, 4_0);
CF_EXPORT
const CFStringRef kCFURLKeysOfUnsetValuesKey CF_AVAILABLE(10_7, 5_0);
- /* If CFURLSetResourcePropertiesForKeys returns an error, this is key in the error's userInfo dictionary to the array of keys of unset values. */
+ /* Key for the resource properties that have not been set after the CFURLSetResourcePropertiesForKeys function returns an error, returned as an array of of CFString objects. */
-/* Discards a cached property value for a specific key */
+/*
+ CFURLClearResourcePropertyCacheForKey
+
+ Discards a cached resource value of a URL.
+
+ Parameters
+ url
+ The URL specifying the resource.
+ key
+ The resource key that identifies the resource property.
+
+ Discussion
+ Discarding a cached resource value may discard other cached resource values, because some resource values are cached as a set of values and because some resource values depend on other resource values (temporary properties have no dependencies). This function is currently applicable only to URLs for file system resources.
+ Symbol is present in iOS 4, but performs no operation.
+ */
CF_EXPORT
void CFURLClearResourcePropertyCacheForKey(CFURLRef url, CFStringRef key) CF_AVAILABLE(10_6, 4_0);
-/* Discards all cached property values */
+/*
+ CFURLClearResourcePropertyCache
+
+ Discards all cached resource values of a URL.
+
+ Parameters
+ url
+ The URL specifying the resource.
+
+ Discussion
+ All temporary properties are also cleared from the URL object's cache. This function is currently applicable only to URLs for file system resources.
+ Symbol is present in iOS 4, but performs no operation.
+ */
CF_EXPORT
void CFURLClearResourcePropertyCache(CFURLRef url) CF_AVAILABLE(10_6, 4_0);
-/* Sets a temporary property value. Temporary properties exist only in memory and are never */
-/* written to resource backing store. Once set, a temporary property value can be fetched */
-/* with CFURLCopyResourcePropertyForKey and CFURLCopyResourcePropertiesForKeys. Temporary property */
-/* values are for client use. Values must be valid Core Foundation types, and will be retained. */
-/* To remove a temporary property value, use CFURLClearResourcePropertyCacheForKey. */
+/*
+ CFURLSetTemporaryResourcePropertyForKey
+
+ Sets a temporary resource value on the URL object.
+
+ Parameters
+ url
+ The URL object.
+ key
+ The resource key that identifies the temporary resource property.
+ propertyValue
+ The resource value.
+
+ Discussion
+ Temporary properties are for client use. Temporary properties exist only in memory and are never written to the resource's backing store. Once set, a temporary value can be copied from the URL object with CFURLCopyResourcePropertyForKey and CFURLCopyResourcePropertiesForKeys. To remove a temporary value from the URL object, use CFURLClearResourcePropertyCacheForKey. Temporary values must be valid Core Foundation types, and will be retained by CFURLSetTemporaryResourcePropertyForKey. Care should be taken to ensure the key that identifies a temporary resource property is unique and does not conflict with system defined keys (using reverse domain name notation in your temporary resource property keys is recommended). This function is currently applicable only to URLs for file system resources.
+ Symbol is present in iOS 4, but performs no operation.
+ */
CF_EXPORT
void CFURLSetTemporaryResourcePropertyForKey(CFURLRef url, CFStringRef key, CFTypeRef propertyValue) CF_AVAILABLE(10_6, 4_0);
-/* Synchronously checks if the resource's backing store is reachable and the resource exists, */
-/* returning true if so. The optional output error can be used to determine the type of reachability */
-/* failure (e.g., file not found, network error, etc.). The error is set to a valid CFErrorRef if */
-/* and only if the function returns false. A valid output error must be released by */
-/* the caller. Checking for resource existence and reachability is appropriate when making decisions */
-/* that do not require other immediate operations on the resource. An example would be */
-/* periodic maintenance of UI state that depends on the existence of a particular document. */
-/* When performing an operation such as opening a file, it is more efficient to */
-/* simply try the operation and handle failures than to check first for reachability. */
+/*
+ CFURLResourceIsReachable
+
+ Returns whether the URL's resource exists and is reachable.
+
+ Parameters
+ url
+ The URL object.
+ error
+ On output when the result is false, the error that occurred. This parameter is optional; if you do not wish the error returned, pass NULL here. The caller is responsible for releasing a valid output error.
+
+ Return Value
+ true if the resource is reachable; otherwise, false.
+
+ Discussion
+ CFURLResourceIsReachable synchronously checks if the resource's backing store is reachable. Checking reachability is appropriate when making decisions that do not require other immediate operations on the resource, e.g. periodic maintenance of UI state that depends on the existence of a specific document. When performing operations such as opening a file or copying resource properties, it is more efficient to simply try the operation and handle failures. This function is currently applicable only to URLs for file system resources. If this function returns false, the optional error is populated. For other URL types, false is returned.
+ Symbol is present in iOS 4, but performs no operation.
+ */
CF_EXPORT
Boolean CFURLResourceIsReachable(CFURLRef url, CFErrorRef *error) CF_AVAILABLE(10_6, 4_0);
+CF_IMPLICIT_BRIDGING_ENABLED
+
/* Properties of File System Resources */
CF_EXPORT
const CFStringRef kCFURLNameKey CF_AVAILABLE(10_6, 4_0);
- /* The resource name provided by the file system (value type CFString) */
+ /* The resource name provided by the file system (Read-write, value type CFString) */
CF_EXPORT
const CFStringRef kCFURLLocalizedNameKey CF_AVAILABLE(10_6, 4_0);
CF_EXPORT
const CFStringRef kCFURLIsPackageKey CF_AVAILABLE(10_6, 4_0);
- /* True for packaged directories (value type CFBoolean) */
+ /* True for packaged directories (Read-only 10_6 and 10_7, read-write 10_8, value type CFBoolean). Note: You can only set or clear this property on directories; if you try to set this property on non-directory objects, the property is ignored. If the directory is a package for some other reason (extension type, etc), setting this property to false will have no effect. */
CF_EXPORT
const CFStringRef kCFURLIsSystemImmutableKey CF_AVAILABLE(10_6, 4_0);
- /* True for system-immutable resources (value type CFBoolean) */
+ /* True for system-immutable resources (Read-write, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLIsUserImmutableKey CF_AVAILABLE(10_6, 4_0);
- /* True for user-immutable resources (value type CFBoolean) */
+ /* True for user-immutable resources (Read-write, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLIsHiddenKey CF_AVAILABLE(10_6, 4_0);
- /* True for resources normally hidden from users (value type CFBoolean) */
+ /* True for resources normally not displayed to users (Read-write, value type CFBoolean). Note: If the resource is a hidden because its name starts with a period, setting this property to false will not change the property. */
CF_EXPORT
const CFStringRef kCFURLHasHiddenExtensionKey CF_AVAILABLE(10_6, 4_0);
- /* True for resources whose filename extension is hidden (value type CFBoolean) */
+ /* True for resources whose filename extension is removed from the localized name property (Read-write, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLCreationDateKey CF_AVAILABLE(10_6, 4_0);
- /* The date the resource was created (value type CFDate) */
+ /* The date the resource was created (Read-write, value type CFDate) */
CF_EXPORT
const CFStringRef kCFURLContentAccessDateKey CF_AVAILABLE(10_6, 4_0);
CF_EXPORT
const CFStringRef kCFURLContentModificationDateKey CF_AVAILABLE(10_6, 4_0);
- /* The time the resource content was last modified (value type CFDate) */
+ /* The time the resource content was last modified (Read-write, value type CFDate) */
CF_EXPORT
const CFStringRef kCFURLAttributeModificationDateKey CF_AVAILABLE(10_6, 4_0);
- /* The time the resource's attributes were last modified (value type CFDate) */
+ /* The time the resource's attributes were last modified (Read-write, value type CFDate) */
CF_EXPORT
const CFStringRef kCFURLLinkCountKey CF_AVAILABLE(10_6, 4_0);
- /* Number of hard links to the resource (Read-only, CFNumber) */
+ /* Number of hard links to the resource (Read-only, value type CFNumber) */
CF_EXPORT
const CFStringRef kCFURLParentDirectoryURLKey CF_AVAILABLE(10_6, 4_0);
- /* URL of the parent directory, if any (Read-only, value type CFURL) */
+ /* The resource's parent directory, if any (Read-only, value type CFURL) */
CF_EXPORT
const CFStringRef kCFURLVolumeURLKey CF_AVAILABLE(10_6, 4_0);
CF_EXPORT
const CFStringRef kCFURLTypeIdentifierKey CF_AVAILABLE(10_6, 4_0);
- /* Uniform type identifier for the resource (Read-only, value type CFString) */
+ /* Uniform type identifier (UTI) for the resource (Read-only, value type CFString) */
CF_EXPORT
const CFStringRef kCFURLLocalizedTypeDescriptionKey CF_AVAILABLE(10_6, 4_0);
- /* User-visible type or "kind" descriptiopn (Read-only, value type CFString) */
+ /* User-visible type or "kind" description (Read-only, value type CFString) */
CF_EXPORT
const CFStringRef kCFURLLabelNumberKey CF_AVAILABLE(10_6, 4_0);
- /* The label number assigned to the resource (value type CFNumber) */
+ /* The label number assigned to the resource (Read-write, value type CFNumber) */
CF_EXPORT
const CFStringRef kCFURLLabelColorKey CF_AVAILABLE(10_6, 4_0);
- /* The color of the assigned label (Read-only, value type CGColorRef, must link with Application Services) */
+ /* The color of the assigned label (Currently not implemented, value type CGColorRef, must link with Application Services) */
CF_EXPORT
const CFStringRef kCFURLLocalizedLabelKey CF_AVAILABLE(10_6, 4_0);
CF_EXPORT
const CFStringRef kCFURLCustomIconKey CF_AVAILABLE(10_6, 4_0);
- /* The custom icon assigned to the resource, if any (value type CGImageRef, must link with Application Services) */
+ /* The custom icon assigned to the resource, if any (Currently not implemented, value type CGImageRef, must link with Application Services) */
CF_EXPORT
const CFStringRef kCFURLFileResourceIdentifierKey CF_AVAILABLE(10_7, 5_0);
CF_EXPORT
const CFStringRef kCFURLFileSecurityKey CF_AVAILABLE(10_7, 5_0);
- /* The file system object's security information encapsulated in a CFFileSecurity object. (Value type CFFileSecurity) */
+ /* The file system object's security information encapsulated in a CFFileSecurity object. (Read-write, value type CFFileSecurity) */
+
+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 kCFURLPathKey CF_AVAILABLE(10_8, 6_0);
+ /* the URL's path as a file system path (Read-only, value type CFString) */
+
+CF_EXPORT
+const CFStringRef kCFURLIsMountTriggerKey CF_AVAILABLE(10_7, 4_0);
+ /* true if this URL is a file system trigger directory. Traversing or opening a file system trigger will cause an attempt to mount a file system on the trigger directory. (Read-only, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLFileResourceTypeKey CF_AVAILABLE(10_7, 5_0);
CF_EXPORT
const CFStringRef kCFURLFileSizeKey CF_AVAILABLE(10_6, 4_0);
- /* Total file size, in bytes (Read-only, value type CFNumber) */
+ /* Total file size in bytes (Read-only, value type CFNumber) */
CF_EXPORT
const CFStringRef kCFURLFileAllocatedSizeKey CF_AVAILABLE(10_6, 4_0);
- /* Total size of blocks allocated (Read-only, value type CFNumber) */
+ /* Total size allocated on disk for the file in bytes (number of blocks times block size) (Read-only, value type CFNumber) */
CF_EXPORT
const CFStringRef kCFURLTotalFileSizeKey CF_AVAILABLE(10_7, 5_0);
- /* Total displayable size of the file, in bytes (this may include space used by metadata), or NULL if not available. (Read-only, value type CFNumber) */
+ /* Total displayable size of the file in bytes (this may include space used by metadata), or NULL if not available. (Read-only, value type CFNumber) */
CF_EXPORT
const CFStringRef kCFURLTotalFileAllocatedSizeKey CF_AVAILABLE(10_7, 5_0);
- /* Total allocated size of the file, in bytes (this may include space used by metadata), or NULL if not available. This can be less than the value returned by kCFURLTotalFileSizeKey if the resource is compressed. (Read-only, value type CFNumber) */
+ /* Total allocated size of the file in bytes (this may include space used by metadata), or NULL if not available. This can be less than the value returned by kCFURLTotalFileSizeKey if the resource is compressed. (Read-only, value type CFNumber) */
CF_EXPORT
const CFStringRef kCFURLIsAliasFileKey CF_AVAILABLE(10_6, 4_0);
- /* true if the url is a Finder alias file, false otherwise ( Read-only, value type CFBooleanRef) */
-
-CF_EXPORT
-const CFStringRef kCFURLIsMountTriggerKey CF_AVAILABLE(10_7, 4_0);
- /* true if this URL is a file system trigger directory. Traversing or opening a file system trigger will cause an attempt to mount a file system on the trigger directory. (Read-only, value type CFBoolean) */
+ /* true if the resource is a Finder alias file or a symlink, false otherwise ( Read-only, value type CFBooleanRef) */
/* Volume Properties */
-/* For convenience, volume properties may be requested from any resource on a volume. */
+/* As a convenience, volume properties can be requested from any file system URL. The value returned will reflect the property value for the volume on which the resource is located. */
CF_EXPORT
const CFStringRef kCFURLVolumeLocalizedFormatDescriptionKey CF_AVAILABLE(10_6, 4_0);
CF_EXPORT
const CFStringRef kCFURLVolumeAvailableCapacityKey CF_AVAILABLE(10_6, 4_0);
- /* Total free space, in bytes (Read-only, value type CFNumber) */
+ /* Total free space in bytes (Read-only, value type CFNumber) */
CF_EXPORT
const CFStringRef kCFURLVolumeResourceCountKey CF_AVAILABLE(10_6, 4_0);
CF_EXPORT
const CFStringRef kCFURLVolumeSupportsPersistentIDsKey CF_AVAILABLE(10_6, 4_0);
- /* Read-only, value type CFBoolean */
+ /* true if the volume format supports persistent object identifiers and can look up file system objects by their IDs (Read-only, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLVolumeSupportsSymbolicLinksKey CF_AVAILABLE(10_6, 4_0);
- /* Read-only, value type CFBoolean */
+ /* true if the volume format supports symbolic links (Read-only, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLVolumeSupportsHardLinksKey CF_AVAILABLE(10_6, 4_0);
- /* Read-only, value type CFBoolean */
+ /* true if the volume format supports hard links (Read-only, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLVolumeSupportsJournalingKey CF_AVAILABLE(10_6, 4_0);
- /* Read-only, value type CFBoolean */
+ /* true if the volume format supports a journal used to speed recovery in case of unplanned restart (such as a power outage or crash). This does not necessarily mean the volume is actively using a journal. (Read-only, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLVolumeIsJournalingKey CF_AVAILABLE(10_6, 4_0);
- /* Read-only, value type CFBoolean */
+ /* true if the volume is currently using a journal for speedy recovery after an unplanned restart. (Read-only, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLVolumeSupportsSparseFilesKey CF_AVAILABLE(10_6, 4_0);
- /* Read-only, value type CFBoolean */
+ /* true if the volume format supports sparse files, that is, files which can have 'holes' that have never been written to, and thus do not consume space on disk. A sparse file may have an allocated size on disk that is less than its logical length. (Read-only, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLVolumeSupportsZeroRunsKey CF_AVAILABLE(10_6, 4_0);
- /* Read-only, value type CFBoolean */
+ /* For security reasons, parts of a file (runs) that have never been written to must appear to contain zeroes. true if the volume keeps track of allocated but unwritten runs of a file so that it can substitute zeroes without actually writing zeroes to the media. (Read-only, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLVolumeSupportsCaseSensitiveNamesKey CF_AVAILABLE(10_6, 4_0);
- /* Read-only, value type CFBoolean */
+ /* true if the volume format treats upper and lower case characters in file and directory names as different. Otherwise an upper case character is equivalent to a lower case character, and you can't have two names that differ solely in the case of the characters. (Read-only, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLVolumeSupportsCasePreservedNamesKey CF_AVAILABLE(10_6, 4_0);
- /* Read-only, value type CFBoolean */
+ /* true if the volume format preserves the case of file and directory names. Otherwise the volume may change the case of some characters (typically making them all upper or all lower case). (Read-only, value type CFBoolean) */
CF_EXPORT
const CFStringRef kCFURLVolumeSupportsRootDirectoryDatesKey CF_AVAILABLE(10_7, 5_0);
CF_EXPORT
const CFStringRef kCFURLVolumeNameKey CF_AVAILABLE(10_7, 5_0);
- /* The name of the volume (settable if kCFURLVolumeSupportsRenamingKey is true, value type CFString) */
+ /* The name of the volume (Read-write, settable if kCFURLVolumeSupportsRenamingKey is true and permissions allow, value type CFString) */
CF_EXPORT
const CFStringRef kCFURLVolumeLocalizedNameKey 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_AVAILABLE(10_7, 5_0);
- /* [0-100] percent of data downloaded. (Read-only, value type double CFNumber) */
+const CFStringRef kCFURLUbiquitousItemPercentDownloadedKey CF_DEPRECATED(10_7, 10_8, 5_0, 6_0);
+ /* Use NSMetadataQuery and NSMetadataUbiquitousItemPercentDownloadedKey on NSMetadataItem instead */
CF_EXPORT
-const CFStringRef kCFURLUbiquitousItemPercentUploadedKey CF_AVAILABLE(10_7, 5_0);
- /* [0-100] percent of data downloaded. (Read-only, value type double CFNumber) */
+const CFStringRef kCFURLUbiquitousItemPercentUploadedKey CF_DEPRECATED(10_7, 10_8, 5_0, 6_0);
+ /* Use NSMetadataQuery and NSMetadataUbiquitousItemPercentUploadedKey on NSMetadataItem instead */
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFURLBookmarkCreationOptions) {
kCFURLBookmarkCreationPreferFileIDResolutionMask = ( 1UL << 8 ), // At resolution time, this alias will prefer resolving by the embedded fileID to the path
kCFURLBookmarkCreationMinimalBookmarkMask = ( 1UL << 9 ), // Creates a bookmark with "less" information, which may be smaller but still be able to resolve in certain ways
kCFURLBookmarkCreationSuitableForBookmarkFile = ( 1UL << 10 ), // includes in the created bookmark those properties which are needed for a bookmark/alias file
+ kCFURLBookmarkCreationWithSecurityScope CF_ENUM_AVAILABLE(10_7,NA) = ( 1UL << 11 ), // Mac OS X 10.7.3 and later, include information in the bookmark data which allows the same sandboxed process to access the resource after being relaunched
+ kCFURLBookmarkCreationSecurityScopeAllowOnlyReadAccess CF_ENUM_AVAILABLE(10_7,NA) = ( 1UL << 12 ), // Mac OS X 10.7.3 and later, if used with kCFURLBookmarkCreationWithSecurityScope, at resolution time only read access to the resource will be granted
};
-#if MAC_OS_X_VERSION_10_7 <= MAC_OS_X_VERSION_MAX_ALLOWED
-enum {
- kCFURLBookmarkCreationWithSecurityScope = ( 1UL << 11 ), // Mac OS X 10.7.3 and later, include information in the bookmark data which allows the same sandboxed process to access the resource after being relaunched
- kCFURLBookmarkCreationSecurityScopeAllowOnlyReadAccess = ( 1UL << 12 ), // Mac OS X 10.7.3 and later, if used with kCFURLBookmarkCreationWithSecurityScope, at resolution time only read access to the resource will be granted
-};
-#endif
-typedef CFOptionFlags CFURLBookmarkCreationOptions;
-
enum {
kCFBookmarkResolutionWithoutUIMask = ( 1UL << 8 ), // don't perform any UI during bookmark resolution
kCFBookmarkResolutionWithoutMountingMask = ( 1UL << 9 ), // don't mount a volume during bookmark resolution
};
-#if MAC_OS_X_VERSION_10_7 <= MAC_OS_X_VERSION_MAX_ALLOWED
enum {
- kCFURLBookmarkResolutionWithSecurityScope = ( 1UL << 10 ), // Mac OS X 10.7.3 and later, extract the security scope included at creation time to provide the ability to access the resource.
+ kCFURLBookmarkResolutionWithSecurityScope CF_ENUM_AVAILABLE(10_7,NA) = ( 1UL << 10 ), // Mac OS X 10.7.3 and later, extract the security scope included at creation time to provide the ability to access the resource.
};
-#endif
+
typedef CFOptionFlags CFURLBookmarkResolutionOptions;
typedef CFOptionFlags CFURLBookmarkFileCreationOptions;
+CF_IMPLICIT_BRIDGING_DISABLED
+
/* @function CFURLCreateBookmarkData
@discussion Create a CFDataRef containing an externalizable representation from a CFURLRef, modified with the given options, including ( at the minimum ) any
properties in the propertiesToInclude array which are retrievable from the given url.
CF_EXPORT
CFDataRef CFURLCreateBookmarkDataFromAliasRecord ( CFAllocatorRef allocatorRef, CFDataRef aliasRecordDataRef ) CF_AVAILABLE_MAC(10_6);
+CF_IMPLICIT_BRIDGING_ENABLED
+
/*! @function CFURLStartAccessingSecurityScopedResource
@discussion Given a CFURLRef created by resolving a bookmark data created with security scope, make the resource referenced by the
url accessible to the process. When access to this resource is no longer needed the client should call
@result returns TRUE if access was granted and FALSE if the url does not reference a security scoped resource, or if some error occurred
which didn't allow access to be granted
*/
+CF_EXPORT
Boolean CFURLStartAccessingSecurityScopedResource(CFURLRef url) CF_AVAILABLE(10_7, NA); // Available in MacOS X 10.7.3 and later
/*! @function CFURLStopAccessingSecurityScopedResource
@discussion Revokes the access granted to the url by a prior successful call to CFURLStartAccessingSecurityScopedResource().
@param url the CFURLRef for the resource to stop accessing.
*/
+CF_EXPORT
void CFURLStopAccessingSecurityScopedResource(CFURLRef url) CF_AVAILABLE(10_7, NA);
#endif /* TARGET_OS_MAC || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE */
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFURL__ */
*/
/* CFURLAccess.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Chris Linn
*/
#include <CoreFoundation/CFNumber.h>
#include <string.h>
#include <ctype.h>
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <pwd.h>
#include <fcntl.h>
#elif DEPLOYMENT_TARGET_WINDOWS
-//#include <winsock2.h>
#include <io.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
-#include <errno.h>
#include <ctype.h>
#else
#error Unknown or unspecified DEPLOYMENT_TARGET
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#include <dlfcn.h>
#endif
CFNumberRef modeNum = (CFNumberRef)value;
CFNumberGetValue(modeNum, kCFNumberSInt32Type, &mode);
} else {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
#define MODE_TYPE mode_t
#elif DEPLOYMENT_TARGET_WINDOWS
#define MODE_TYPE uint16_t
alloc = (CFAllocatorRef)CFRetain(__CFGetDefaultAllocator());
releaseAlloc = true;
}
- if (!_CFReadBytesFromFile(alloc, url, &bytes, &length, 0)) {
+ if (!_CFReadBytesFromFile(alloc, url, &bytes, &length, 0, 0)) {
if (errorCode) *errorCode = kCFURLUnknownError;
*fetchedData = NULL;
success = false;
if (data) {
if (CFURLHasDirectoryPath(url)) {
// Create a directory
-#if DEPLOYMENT_TARGET_WINDOWS
- wchar_t cPath[CFMaxPathSize];
- if (!_CFURLGetWideFileSystemRepresentation(url, true, cPath, CFMaxPathSize))
-#else
char cPath[CFMaxPathSize];
if (!CFURLGetFileSystemRepresentation(url, true, (unsigned char *)cPath, CFMaxPathSize))
-#endif
{
if (errorCode) *errorCode = kCFURLImproperArgumentsError;
success = false;
} else {
-#if DEPLOYMENT_TARGET_WINDOWS
- success = _CFCreateDirectoryWide(cPath);
-#else
success = _CFCreateDirectory(cPath);
-#endif
if (!success && errorCode) *errorCode = kCFURLUnknownError;
}
} else {
*/
/* CFURLAccess.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFURLACCESS__)
/* Common error codes (returned only by the older APIs that predate CFError) */
-enum {
- kCFURLUnknownError = -10,
- kCFURLUnknownSchemeError = -11,
- kCFURLResourceNotFoundError = -12,
- kCFURLResourceAccessViolationError = -13,
- kCFURLRemoteHostUnavailableError = -14,
- kCFURLImproperArgumentsError = -15,
- kCFURLUnknownPropertyKeyError = -16,
- kCFURLPropertyKeyUnavailableError = -17,
- kCFURLTimeoutError = -18
+typedef CF_ENUM(CFIndex, CFURLError) {
+ kCFURLUnknownError = -10L,
+ kCFURLUnknownSchemeError = -11L,
+ kCFURLResourceNotFoundError = -12L,
+ kCFURLResourceAccessViolationError = -13L,
+ kCFURLRemoteHostUnavailableError = -14L,
+ kCFURLImproperArgumentsError = -15L,
+ kCFURLUnknownPropertyKeyError = -16L,
+ kCFURLPropertyKeyUnavailableError = -17L,
+ kCFURLTimeoutError = -18L
};
-typedef CFIndex CFURLError;
/* Older property keys */
*/
/* CFURLPriv.h
- Copyright (c) 2008-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2008-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFURLPRIV__)
#if TARGET_OS_MAC
-#if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
enum {
// Resource I/O related errors, with kCFErrorURLKey containing URL
kCFURLNoSuchResourceError = 4, // Attempt to do a file system operation on a non-existent file
kCFURLWriteUnsupportedSchemeError = 518, // Write error (unsupported URL scheme)
kCFURLWriteOutOfSpaceError = 640, // Write error (out of storage space)
kCFURLWriteVolumeReadOnlyError = 642, // Write error (readonly volume)
-};
-#endif
-
-
-enum {
- kCFURLFileReferencePathStyle = 14,
-};
+} CF_ENUM_AVAILABLE(10_5, 2_0);
/*
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) */
-/* OBSOLETE */CF_EXPORT const CFStringRef _kCFURLFilePathKey CF_DEPRECATED(10_0, 10_6, 2_0, 4_0);
- /* _kCFURLFilePathKey was never implemented. Use _kCFURLPathKey instead. */
-
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) */
CF_EXPORT const CFStringRef _kCFURLCanSetApplicationHighResolutionModeIsMagnifiedKey CF_AVAILABLE(10_7, NA);
/* True if the app can run in either magnified or native resolution modes (Read only, CFBoolean) */
+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) */
+
/* Additional volume properties */
CF_EXPORT const CFStringRef _kCFURLVolumeRefNumKey CF_AVAILABLE(10_6, 4_0);
/*
File resource properties which can be obtained with _CFURLCopyFilePropertyValuesAndFlags().
*/
-enum {
+typedef CF_OPTIONS(unsigned long long, CFURLFilePropertyBitmap) {
kCFURLName = 0x0000000000000001,
kCFURLLinkCount = 0x0000000000000002,
kCFURLVolumeIdentifier = 0x0000000000000004,
kCFURLFinderInfo = 0x0000000000000800,
kCFURLFileSecurity = 0x0000000000001000,
};
-typedef unsigned long long CFURLFilePropertyBitmap;
/*
The structure where _CFURLCopyFilePropertyValuesAndFlags() returns file resource properties.
/*
Volume property flags
*/
-enum {
+typedef CF_OPTIONS(unsigned long long, CFURLVolumePropertyFlags) {
kCFURLVolumeIsLocal = 0x1LL, // Local device (vs. network device)
kCFURLVolumeIsAutomount = 0x2LL, // Mounted by the automounter
kCFURLVolumeDontBrowse = 0x4LL, // Hidden from user browsing
kCFURLVolumeHas64BitObjectIDs = 0x1000000000000000LL,
kCFURLVolumePropertyFlagsAll = 0xffffffffffffffffLL
};
-typedef unsigned long long CFURLVolumePropertyFlags;
/*
CF_EXPORT
CFArrayRef _CFURLCreateDisplayPathComponentsArray(CFURLRef url, CFErrorRef *error) CF_AVAILABLE(10_7, 4_0);
-#if 0
-/* Not implemented */
-CF_EXPORT
-CFURLRef _CFURLCreateFileIDURLFromFSRef(CFAllocatorRef allocator, const struct FSRef *fsRef);
-#endif
-
-CF_EXPORT
-CFURLRef _CFURLCreateAbsoluteURLWithDirectoryURLAndName(CFAllocatorRef allocator, CFURLRef directoryURL, CFStringRef name) CF_AVAILABLE(10_6, 4_0);
-
/* Returns true for URLs that locate file system resources. */
CF_EXPORT
Boolean _CFURLIsFileURL(CFURLRef url) CF_AVAILABLE(10_6, 4_0);
};
enum {
- kCFBookmarkResolutionPerformRelativeResolutionFirstMask = ( 1 << 10 ), // perform relative resolution before absolute resolution. If this bit is set, for this to be useful a relative URL must also have been passed in and the bookmark when created must have been created relative to another url.
+ kCFBookmarkResolutionPerformRelativeResolutionFirstMask CF_ENUM_AVAILABLE(10_8,6_0) = ( 1 << 11 ), // perform relative resolution before absolute resolution. If this bit is set, for this to be useful a relative URL must also have been passed in and the bookmark when created must have been created relative to another url.
};
-enum {
+typedef CF_ENUM(CFIndex, CFURLBookmarkMatchResult) {
kCFURLBookmarkComparisonUnableToCompare = 0x00000000, /* the two bookmarks could not be compared for some reason */
kCFURLBookmarkComparisonNoMatch = 0x00001000, /* Bookmarks do not refer to the same item */
kCFURLBookmarkComparisonUnlikelyToMatch = 0x00002000, /* it is unlikely that the two items refer to the same filesystem item */
kCFURLBookmarkComparisonMatch = 0x00008000, /* the two items refer to the same item, but other information in the bookmarks may not match */
kCFURLBookmarkComparisonExactMatch = 0x0000f000 /* the two bookmarks are identical */
};
-typedef CFIndex CFURLBookmarkMatchResult;
/* Keys specific to bookmarks at this time */
CF_EXPORT const CFStringRef _kCFURLPropertyKeyFullPathString; // the full filesystem path of the item the bookmark was create against
*/
/* CFUUID.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: David Smith
*/
#include <CoreFoundation/CFUUID.h>
#include "CFInternal.h"
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
-#include <uuid/uuid.h>
-#endif
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
#include <dispatch/dispatch.h>
#if DEPLOYMENT_TARGET_WINDOWS
#include <Rpc.h>
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#include <uuid/uuid.h>
#endif
CFUUIDRef CFUUIDCreate(CFAllocatorRef alloc) {
*/
/* CFUUID.h
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFUUID__)
#include <CoreFoundation/CFBase.h>
#include <CoreFoundation/CFString.h>
+CF_IMPLICIT_BRIDGING_ENABLED
CF_EXTERN_C_BEGIN
typedef const struct __CFUUID * CFUUIDRef;
CFUUIDRef CFUUIDCreateFromUUIDBytes(CFAllocatorRef alloc, CFUUIDBytes bytes);
CF_EXTERN_C_END
+CF_IMPLICIT_BRIDGING_DISABLED
#endif /* ! __COREFOUNDATION_CFUUID__ */
*/
/* CFUniChar.c
- Copyright (c) 2001-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2001-2012, Apple Inc. All rights reserved.
Responsibility: Aki Inoue
*/
#include "CFStringEncodingConverterExt.h"
#include "CFUnicodeDecomposition.h"
#include "CFUniCharPriv.h"
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
#define __kCFCharacterSetDir "/System/Library/CoreServices"
-#elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#elif DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD || DEPLOYMENT_TARGET_EMBEDDED_MINI
#define __kCFCharacterSetDir "/usr/local/share/CoreFoundation"
#elif DEPLOYMENT_TARGET_WINDOWS
#define __kCFCharacterSetDir "\\Windows\\CoreFoundation"
// Memory map the file
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
CF_INLINE void __CFUniCharCharacterSetPath(char *cpath) {
#elif DEPLOYMENT_TARGET_WINDOWS
CF_INLINE void __CFUniCharCharacterSetPath(wchar_t *wpath) {
}
#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
static bool __CFUniCharLoadBytesFromFile(const char *fileName, const void **bytes, int64_t *fileSize) {
#elif DEPLOYMENT_TARGET_WINDOWS
static bool __CFUniCharLoadBytesFromFile(const wchar_t *fileName, const void **bytes, int64_t *fileSize) {
#endif // USE_MACHO_SEGMENT
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
static bool __CFUniCharLoadFile(const char *bitmapName, const void **bytes, int64_t *fileSize) {
#elif DEPLOYMENT_TARGET_WINDOWS
static bool __CFUniCharLoadFile(const wchar_t *bitmapName, const void **bytes, int64_t *fileSize) {
return *bytes ? true : false;
#else
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
char cpath[MAXPATHLEN];
__CFUniCharCharacterSetPath(cpath);
strlcat(cpath, bitmapName, MAXPATHLEN);
static CFSpinLock_t __CFUniCharBitmapLock = CFSpinLockInit;
-#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 !defined(CF_UNICHAR_BITMAP_FILE)
#if USE_MACHO_SEGMENT
#define CF_UNICHAR_BITMAP_FILE "__csbitmaps"
static CFSpinLock_t __CFUniCharMappingTableLock = CFSpinLockInit;
-#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 __CF_BIG_ENDIAN__
#if USE_MACHO_SEGMENT
#define MAPPING_TABLE_FILE "__data"
#define LITHUANIAN_LANG_CODE (0x6C74) // lt
#define AZERI_LANG_CODE (0x617A) // az
#define DUTCH_LANG_CODE (0x6E6C) // nl
+#define GREEK_LANG_CODE (0x656C) // el
#else
#define TURKISH_LANG_CODE (0x7274) // tr
#define LITHUANIAN_LANG_CODE (0x746C) // lt
#define AZERI_LANG_CODE (0x7A61) // az
#define DUTCH_LANG_CODE (0x6C6E) // nl
+#define GREEK_LANG_CODE (0x6C65) // el
#endif
CFIndex CFUniCharMapCaseTo(UTF32Char theChar, UTF16Char *convertedChar, CFIndex maxLength, uint32_t ctype, uint32_t flags, const uint8_t *langCode) {
}
if (langCode) {
+ if (flags & kCFUniCharCaseMapGreekTonos) { // localized Greek uppercasing
+ if (theChar == 0x0301) { // GREEK TONOS
+ return 0;
+ } else if (theChar == 0x0344) {// COMBINING GREEK DIALYTIKA TONOS
+ *convertedChar = 0x0308; // COMBINING GREEK DIALYTIKA
+ return 1;
+ } else if (CFUniCharIsMemberOf(theChar, kCFUniCharDecomposableCharacterSet)) {
+ UTF32Char buffer[MAX_DECOMPOSED_LENGTH];
+ CFIndex length = CFUniCharDecomposeCharacter(theChar, buffer, MAX_DECOMPOSED_LENGTH);
+
+ if (length > 1) {
+ UTF32Char *characters = buffer + 1;
+ UTF32Char *tail = buffer + length;
+
+ while (characters < tail) {
+ if (*characters == 0x0301) break;
+ ++characters;
+ }
+
+ if (characters < tail) { // found a tonos
+ CFIndex convertedLength = CFUniCharMapCaseTo(*buffer, convertedChar, maxLength, ctype, 0, langCode);
+
+ if (convertedLength == 0) {
+ *convertedChar = (UTF16Char)*buffer;
+ convertedLength = 1;
+ }
+
+ characters = buffer + 1;
+
+ while (characters < tail) {
+ if (*characters != 0x0301) { // not tonos
+ if (*characters < 0x10000) { // BMP
+ convertedChar[convertedLength] = (UTF16Char)*characters;
+ ++convertedLength;
+ } else {
+ UTF32Char character = *characters - 0x10000;
+ convertedChar[convertedLength++] = (UTF16Char)((character >> 10) + 0xD800UL);
+ convertedChar[convertedLength++] = (UTF16Char)((character & 0x3FF) + 0xDC00UL);
+ }
+ }
+ ++characters;
+ }
+
+ return convertedLength;
+ }
+ }
+ }
+ }
switch (*(uint16_t *)langCode) {
case LITHUANIAN_LANG_CODE:
if (theChar == 0x0307 && (flags & kCFUniCharCaseMapAfter_i)) {
}
}
}
+
+ if (kCFUniCharCaseMapGreekTonos & lastFlags) { // still searching for tonos
+ if (CFUniCharIsMemberOf(theChar, kCFUniCharNonBaseCharacterSet)) {
+ return kCFUniCharCaseMapGreekTonos;
+ }
+ }
+ if (((theChar >= 0x0370) && (theChar < 0x0400)) || ((theChar >= 0x1F00) && (theChar < 0x2000))) { // Greek/Coptic & Greek extended ranges
+ if (((type == kCFUniCharToUppercase) || (type == kCFUniCharToTitlecase))&& (CFUniCharIsMemberOf(theChar, kCFUniCharLetterCharacterSet))) return kCFUniCharCaseMapGreekTonos;
+ }
}
return 0;
}
static CFSpinLock_t __CFUniCharPropTableLock = CFSpinLockInit;
-#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 USE_MACHO_SEGMENT
#define PROP_DB_FILE "__properties"
#else
*/
/* CFUniChar.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFUNICHAR__)
kCFUniCharCaseMapFinalSigma = (1UL << 0),
kCFUniCharCaseMapAfter_i = (1UL << 1),
kCFUniCharCaseMapMoreAbove = (1UL << 2),
- kCFUniCharCaseMapDutchDigraph = (1UL << 3)
+ kCFUniCharCaseMapDutchDigraph = (1UL << 3),
+ kCFUniCharCaseMapGreekTonos = (1UL << 4)
};
CF_EXPORT CFIndex CFUniCharMapCaseTo(UTF32Char theChar, UTF16Char *convertedChar, CFIndex maxLength, uint32_t ctype, uint32_t flags, const uint8_t *langCode);
*/
/* CFUniCharPriv.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFUNICHARPRIV__)
*/
/* CFUnicodeDecomposition.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Aki Inoue
*/
* CoreFoundation
*
* Created by aki on Wed Oct 03 2001.
- * Copyright (c) 2001-2011, Apple Inc. All rights reserved.
+ * Copyright (c) 2001-2012, Apple Inc. All rights reserved.
*
*/
*/
/* CFUnicodePrecomposition.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: Aki Inoue
*/
* CoreFoundation
*
* Created by aki on Wed Oct 03 2001.
- * Copyright (c) 2001-2011, Apple Inc. All rights reserved.
+ * Copyright (c) 2001-2012, Apple Inc. All rights reserved.
*
*/
*/
/* CFUserNotification.c
- Copyright (c) 2000-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2000-2012, Apple Inc. All rights reserved.
Original Author: Doug Davidson
Responsibility: Kevin Perry
*/
if (__CFOASafe) __CFSetLastAllocationEventName(msg, "CFUserNotification (temp)");
if (msg) {
memset(msg, 0, size);
- msg->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
+ msg->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, (replyPort == MACH_PORT_NULL) ? 0 : MACH_MSG_TYPE_MAKE_SEND_ONCE);
msg->header.msgh_size = size;
msg->header.msgh_remote_port = serverPort;
msg->header.msgh_local_port = replyPort;
SInt32 CFUserNotificationUpdate(CFUserNotificationRef userNotification, CFTimeInterval timeout, CFOptionFlags flags, CFDictionaryRef dictionary) {
CHECK_FOR_FORK();
SInt32 retval = ERR_SUCCESS;
- if (userNotification && MACH_PORT_NULL != userNotification->_replyPort) retval = _CFUserNotificationSendRequest(CFGetAllocator(userNotification), userNotification->_sessionID, userNotification->_replyPort, userNotification->_token, timeout, flags|kCFUserNotificationUpdateFlag, dictionary);
+ if (userNotification && MACH_PORT_NULL != userNotification->_replyPort) {
+ // Avoid including a new send-once right with update/cancel messages by passing MACH_PORT_NULL, since the server doesn't need to use them.
+ retval = _CFUserNotificationSendRequest(CFGetAllocator(userNotification), userNotification->_sessionID, MACH_PORT_NULL, userNotification->_token, timeout, flags|kCFUserNotificationUpdateFlag, dictionary);
+ }
return retval;
}
SInt32 CFUserNotificationCancel(CFUserNotificationRef userNotification) {
CHECK_FOR_FORK();
SInt32 retval = ERR_SUCCESS;
- if (userNotification && MACH_PORT_NULL != userNotification->_replyPort) retval = _CFUserNotificationSendRequest(CFGetAllocator(userNotification), userNotification->_sessionID, userNotification->_replyPort, userNotification->_token, 0, kCFUserNotificationCancelFlag, NULL);
+ if (userNotification && MACH_PORT_NULL != userNotification->_replyPort) {
+ // Avoid including a new send-once right with update/cancel messages by passing MACH_PORT_NULL, since the server doesn't need to use them.
+ retval = _CFUserNotificationSendRequest(CFGetAllocator(userNotification), userNotification->_sessionID, MACH_PORT_NULL, userNotification->_token, 0, kCFUserNotificationCancelFlag, NULL);
+ }
return retval;
}
*/
/* CFUserNotification.h
- Copyright (c) 2000-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2000-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFUSERNOTIFICATION__)
*/
/* CFUtilities.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: Tony Parker
*/
#define ASL_LEVEL_DEBUG 7
#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#include <unistd.h>
#include <sys/uio.h>
#include <mach/mach.h>
#undef ELF_STEP
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
__private_extern__ uintptr_t __CFFindPointer(uintptr_t ptr, uintptr_t start) {
vm_map_t task = mach_task_self();
mach_vm_address_t address = start;
#endif
__private_extern__ void *__CFStartSimpleThread(void *func, void *arg) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
pthread_attr_t attr;
pthread_t tid = 0;
pthread_attr_init(&attr);
static CFDictionaryRef _CFCopyVersionDictionary(CFStringRef path) {
CFPropertyListRef plist = NULL;
+
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
CFDataRef data;
CFURLRef url;
-
+
url = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, path, kCFURLPOSIXPathStyle, false);
if (url && CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault, url, &data, NULL, NULL, NULL)) {
plist = CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, data, kCFPropertyListMutableContainers, NULL);
CFRelease(data);
}
if (url) CFRelease(url);
-
+
if (plist) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
CFBundleRef locBundle = NULL;
CFStringRef fullVersion, vers, versExtra, build;
CFStringRef versionString = _CFCopyLocalizedVersionKey(&locBundle, _kCFSystemVersionProductVersionStringKey);
CFRelease(buildString);
CFRelease(fullVersionString);
CFRelease(fullVersion);
-#endif
}
+#elif DEPLOYMENT_TARGET_WINDOWS
+ OSVERSIONINFOEX osvi;
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ BOOL result = GetVersionEx((OSVERSIONINFO *)&osvi);
+ if (!result) return NULL;
+
+ plist = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ // e.g. 10.7
+ CFStringRef versionString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%ld.%ld(%ld,%ld)"), osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.wServicePackMajor, osvi.wServicePackMinor);
+
+ // e.g. 11A508
+ CFStringRef buildString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%ld"), osvi.dwBuildNumber);
+
+ CFDictionarySetValue((CFMutableDictionaryRef)plist, _kCFSystemVersionProductVersionKey, versionString);
+ CFDictionarySetValue((CFMutableDictionaryRef)plist, _kCFSystemVersionBuildVersionKey, buildString);
+ CFDictionarySetValue((CFMutableDictionaryRef)plist, _kCFSystemVersionProductNameKey, CFSTR("Windows")); // hard coded for now
+
+ CFRelease(versionString);
+ CFRelease(buildString);
+#endif
return (CFDictionaryRef)plist;
}
}
return dyfunc;
}
-#endif
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
__private_extern__ void *__CFLookupCFNetworkFunction(const char *name) {
static void *image = NULL;
if (NULL == image) {
path = __CFgetenv("CFNETWORK_LIBRARY_PATH");
}
if (!path) {
-#if DEPLOYMENT_TARGET_MACOSX
- path = "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CFNetwork.framework/Versions/A/CFNetwork";
-#else
path = "/System/Library/Frameworks/CFNetwork.framework/CFNetwork";
-#endif
}
image = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
}
v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
v = (v + (v >> 4)) & 0xf0f0f0f0f0f0f0fULL;
pcnt = (v * 0x0101010101010101ULL) >> ((sizeof(v) - 1) * 8);
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
int32_t mib[] = {CTL_HW, HW_AVAILCPU};
size_t len = sizeof(pcnt);
int32_t result = sysctl(mib, sizeof(mib) / sizeof(int32_t), &pcnt, &len, NULL, 0);
return pcnt;
}
+__private_extern__ 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;
+ if (0 == pthread_getugid_np(&uid, &gid)) {
+ if (euid) *euid = uid;
+ if (egid) *egid = gid;
+ } else
+#endif
+ {
+ if (euid) *euid = geteuid();
+ if (egid) *egid = getegid();
+ }
+}
+
const char *_CFPrintForDebugger(const void *obj) {
static char *result = NULL;
CFStringRef str;
}
}
if (!lastNL) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
fprintf_l(file, NULL, "\n");
#else
fprintf(file, NULL, "\n");
typedef void (*CFLogFunc)(int32_t lev, const char *message, size_t length, char withBanner);
static Boolean also_do_stderr() {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_EMBEDDED_MINI
+ // just log to stderr, other logging facilities are out
+ return true;
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if (!issetugid() && __CFgetenv("CFLOG_FORCE_STDERR")) {
return true;
}
char *time = NULL;
char *thread = NULL;
char *uid = NULL;
-#if !(DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED)
+#if DEPLOYMENT_TARGET_WINDOWS
int bannerLen = 0;
#endif
+#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) {
CFAbsoluteTime at = CFAbsoluteTimeGetCurrent();
}
after_banner:;
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
- asprintf(&uid, "%d", geteuid());
+ uid_t euid;
+ __CFGetUGIDs(&euid, NULL);
+ asprintf(&uid, "%d", euid);
aslclient asl = asl_open(NULL, __CFBundleMainID[0] ? __CFBundleMainID : "com.apple.console", ASL_OPT_NO_DELAY);
aslmsg msg = asl_new(ASL_TYPE_MSG);
asl_set(msg, "CFLog Local Time", time); // not to be documented, not public API
asl_free(msg);
asl_close(asl);
#endif
+#endif // DEPLOYMENT_TARGET
if (also_do_stderr()) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
struct iovec v[3];
v[0].iov_base = banner;
v[0].iov_len = banner ? strlen(banner) : 0;
}
CF_EXPORT void _CFLogvEx(CFLogFunc logit, CFStringRef (*copyDescFunc)(void *, const void *), CFDictionaryRef formatOptions, int32_t lev, CFStringRef format, va_list args) {
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
uintptr_t val = (uintptr_t)_CFGetTSD(__CFTSDKeyIsInCFLog);
if (3 < val) return; // allow up to 4 nested invocations
_CFSetTSD(__CFTSDKeyIsInCFLog, (void *)(val + 1), NULL);
}
if (buf) free(buf);
if (str) CFRelease(str);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
_CFSetTSD(__CFTSDKeyIsInCFLog, (void *)val, NULL);
#endif
}
__CFSpinLock(&__CFProcessKillingLock);
__CFProcessKillingDisablingCount--;
if (__CFProcessKillingDisablingCount==0 && !__CFProcessKillingWasTurnedOn) {
- int64_t transactionsAreToBeEnabled = 1;
- int64_t transactionsWereAlreadyEnabled = 0;
- vproc_err_t verr = vproc_swap_integer(NULL, VPROC_GSK_TRANSACTIONS_ENABLED, &transactionsAreToBeEnabled, &transactionsWereAlreadyEnabled);
- if (!verr) {
- if (!transactionsWereAlreadyEnabled) {
- // We set __CFProcessKillingWasTurnedOn below regardless of success because there's no point in retrying.
- } // else this process was launched by launchd with transactions already enabled because EnableTransactions was set to true in the launchd .plist file.
- } // else this process was not launched by launchd and the fix for 6416724 is not in the build yet.
+ _vproc_transactions_enable();
__CFProcessKillingWasTurnedOn = true;
} else {
// Mail seems to have sudden termination disabling/enabling imbalance bugs that make _vproc_transaction_end() kill the app but we don't want that to prevent our submission of the fix 6382488.
#endif
#if 0
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
typedef void (^ThrottleTypeA)(void); // allows calls per nanoseconds
typedef void (^ThrottleTypeB)(uint64_t amt); // allows amount per nanoseconds
#endif
#endif
+#pragma mark File Reading
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#if DEPLOYMENT_TARGET_WINDOWS
+#include <io.h>
+#include <direct.h>
+#define close _close
+#define write _write
+#define read _read
+#define open _NS_open
+#define stat _NS_stat
+#define fstat _fstat
+#define statinfo _stat
+
+#define mach_task_self() 0
+
+#else
+#define statinfo stat
+#endif
+
+static CFErrorRef _CFErrorWithFilePathCodeDomain(CFStringRef domain, CFIndex code, CFStringRef path) {
+ CFStringRef key = CFSTR("NSFilePath");
+ CFDictionaryRef userInfo = CFDictionaryCreate(kCFAllocatorSystemDefault, (const void **)&key, (const void **)&path, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFErrorRef result = CFErrorCreate(kCFAllocatorSystemDefault, domain, code, userInfo);
+ CFRelease(userInfo);
+ return result;
+}
+
+// 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) {
+ void *bytes = NULL;
+ unsigned long length;
+ char cpath[CFMaxPathSize];
+ if (!CFStringGetFileSystemRepresentation(path, cpath, CFMaxPathSize)) {
+ // TODO: real error codes
+ if (errorPtr) *errorPtr = _CFErrorWithFilePathCodeDomain(kCFErrorDomainCocoa, -1, path);
+ return false;
+ }
+
+ struct statinfo statBuf;
+ int32_t fd = -1;
+
+ fd = open(cpath, O_RDONLY|CF_OPENFLGS, 0666);
+ if (fd < 0) {
+ if (errorPtr) *errorPtr = _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX, errno, path);
+ return false;
+ }
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
+ if (uncached) (void)fcntl(fd, F_NOCACHE, 1); // Non-zero arg turns off caching; we ignore error as uncached is just a hint
+#endif
+ if (fstat(fd, &statBuf) < 0) {
+ int32_t savederrno = errno;
+ close(fd);
+ if (errorPtr) *errorPtr = _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX, savederrno, path);
+ return false;
+ }
+ if ((statBuf.st_mode & S_IFMT) != S_IFREG) {
+ close(fd);
+ if (errorPtr) *errorPtr = _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX, EACCES, path);
+ return false;
+ }
+ if (statBuf.st_size < 0LL) { // too small
+ close(fd);
+ if (errorPtr) *errorPtr = _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX, ENOMEM, path);
+ return false;
+ }
+#if __LP64__
+#else
+ if (statBuf.st_size > (1LL << 31)) { // refuse to do more than 2GB
+ close(fd);
+ if (errorPtr) *errorPtr = _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX, EFBIG, path);
+ return false;
+ }
+#endif
+
+ 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
+ } else if (map) {
+ if((void *)-1 == (bytes = mmap(0, (size_t)statBuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0))) {
+ int32_t savederrno = errno;
+ close(fd);
+ if (errorPtr) *errorPtr = _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX, savederrno, path);
+ return false;
+ }
+ length = (unsigned long)statBuf.st_size;
+ } else {
+ bytes = malloc(statBuf.st_size);
+ if (bytes == NULL) {
+ close(fd);
+ if (errorPtr) *errorPtr = _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX, ENOMEM, path);
+ return false;
+ }
+ size_t numBytesRemaining = (size_t)statBuf.st_size;
+ void *readLocation = bytes;
+ while (numBytesRemaining > 0) {
+ size_t numBytesRequested = (numBytesRemaining < (1LL << 31)) ? numBytesRemaining : ((1LL << 31) - 1); // This loop is basically a workaround for 4870206
+ ssize_t numBytesRead = read(fd, readLocation, numBytesRequested);
+ if (numBytesRead <= 0) {
+ if (numBytesRead < 0) {
+ int32_t savederrno = errno;
+ free(bytes);
+ close(fd);
+ if (errorPtr) *errorPtr = _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX, savederrno, path);
+ bytes = NULL;
+ return false;
+ } else {
+ // This is a bizarre case; 0 bytes read. Might indicate end-of-file?
+ break;
+ }
+ } else {
+ readLocation += numBytesRead;
+ numBytesRemaining -= numBytesRead;
+ }
+ }
+ length = (unsigned long)statBuf.st_size - numBytesRemaining;
+ }
+#else
+ } else {
+ bytes = malloc(statBuf.st_size);
+ DWORD numBytesRead;
+ if (!ReadFile((HANDLE)_get_osfhandle(fd), bytes, statBuf.st_size, &numBytesRead, NULL)) {
+ DWORD lastError = GetLastError();
+ if (errorPtr) *errorPtr = _CFErrorWithFilePathCodeDomain(kCFErrorDomainPOSIX, lastError, path);
+ free(bytes);
+ close(fd);
+ errno = lastError;
+ bytes = NULL;
+ return false;
+ }
+ length = numBytesRead;
+ }
+#endif
+ close(fd);
+ *outBytes = bytes;
+ *outLength = length;
+ return true;
+}
Copyright 2009-2011, Apple Inc. All rights reserved.
Responsibility: CFLite Team
*/
-const unsigned char kCFCoreFoundationVersionString[] = "@(#)PROGRAM:CoreFoundation PROJECT:CoreFoundation-635.21 SYSTEM:Darwin DEVELOPER:unknown BUILT:" __DATE__ " " __TIME__ "\n";
-double kCFCoreFoundationVersionNumber = (double)635.21;
+const unsigned char kCFCoreFoundationVersionString[] = "@(#)PROGRAM:CoreFoundation PROJECT:CoreFoundation-744 SYSTEM:Darwin DEVELOPER:unknown BUILT:" __DATE__ " " __TIME__ "\n";
+double kCFCoreFoundationVersionNumber = (double)744;
/*
CFWindowsUtilities.c
- Copyright (c) 2008-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2008-2012, Apple Inc. All rights reserved.
Responsibility: Tony Parker
*/
*/
/* CFXMLInputStream.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: David Smith
*/
*/
/* CFXMLInputStream.h
- Copyright (c) 2000-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2000-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_CFXMLINPUTSTREAM__)
*/
/* CFXMLNode.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: David Smith
*/
*/
/* CFXMLNode.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
-/* CFXMLParser (and thus CFXMLNode) are deprecated. Clients should be aware of the fact that CFXMLParser has
- some serious deficiencies in terms of both performance and standards compliance and should migrate their
- XML parsing to NSXMLParser, NSXMLDocument, or other XML parsing technologies.
- */
+/* 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. */
#if !defined(__COREFOUNDATION_CFXMLNODE__)
#define __COREFOUNDATION_CFXMLNODE__ 1
*/
/* Type codes for the different possible XML nodes; this list may grow.*/
-enum {
+typedef CF_ENUM(CFIndex, CFXMLNodeTypeCode) {
kCFXMLNodeTypeDocument = 1,
kCFXMLNodeTypeElement = 2,
kCFXMLNodeTypeAttribute = 3,
kCFXMLNodeTypeElementTypeDeclaration = 14,
kCFXMLNodeTypeAttributeListDeclaration = 15
};
-typedef CFIndex CFXMLNodeTypeCode;
typedef struct {
CFDictionaryRef attributes;
CFXMLAttributeDeclarationInfo *attributes;
} CFXMLAttributeListDeclarationInfo;
-enum {
+typedef CF_ENUM(CFIndex, CFXMLEntityTypeCode) {
kCFXMLEntityTypeParameter, /* Implies parsed, internal */
kCFXMLEntityTypeParsedInternal,
kCFXMLEntityTypeParsedExternal,
kCFXMLEntityTypeUnparsed,
kCFXMLEntityTypeCharacter
};
-typedef CFIndex CFXMLEntityTypeCode;
typedef struct {
CFXMLEntityTypeCode entityType;
*/
CF_EXPORT
-CFTypeID CFXMLNodeGetTypeID(void);
+CFTypeID CFXMLNodeGetTypeID(void) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Creates a new node based on xmlType, dataString, and additionalInfoPtr. version (together with xmlType) determines the expected structure of additionalInfoPtr */
CF_EXPORT
-CFXMLNodeRef CFXMLNodeCreate(CFAllocatorRef alloc, CFXMLNodeTypeCode xmlType, CFStringRef dataString, const void *additionalInfoPtr, CFIndex version);
+CFXMLNodeRef CFXMLNodeCreate(CFAllocatorRef alloc, CFXMLNodeTypeCode xmlType, CFStringRef dataString, const void *additionalInfoPtr, CFIndex version) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Creates a copy of origNode (which may not be NULL). */
CF_EXPORT
-CFXMLNodeRef CFXMLNodeCreateCopy(CFAllocatorRef alloc, CFXMLNodeRef origNode);
+CFXMLNodeRef CFXMLNodeCreateCopy(CFAllocatorRef alloc, CFXMLNodeRef origNode) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
CF_EXPORT
-CFXMLNodeTypeCode CFXMLNodeGetTypeCode(CFXMLNodeRef node);
+CFXMLNodeTypeCode CFXMLNodeGetTypeCode(CFXMLNodeRef node) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
CF_EXPORT
-CFStringRef CFXMLNodeGetString(CFXMLNodeRef node);
+CFStringRef CFXMLNodeGetString(CFXMLNodeRef node) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
CF_EXPORT
-const void *CFXMLNodeGetInfoPtr(CFXMLNodeRef node);
+const void *CFXMLNodeGetInfoPtr(CFXMLNodeRef node) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
CF_EXPORT
-CFIndex CFXMLNodeGetVersion(CFXMLNodeRef node);
+CFIndex CFXMLNodeGetVersion(CFXMLNodeRef node) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* CFXMLTreeRef */
/* Creates a childless, parentless tree from node */
CF_EXPORT
-CFXMLTreeRef CFXMLTreeCreateWithNode(CFAllocatorRef allocator, CFXMLNodeRef node);
+CFXMLTreeRef CFXMLTreeCreateWithNode(CFAllocatorRef allocator, CFXMLNodeRef node) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Extracts and returns the node stored in xmlTree */
CF_EXPORT
-CFXMLNodeRef CFXMLTreeGetNode(CFXMLTreeRef xmlTree);
+CFXMLNodeRef CFXMLTreeGetNode(CFXMLTreeRef xmlTree) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
CF_EXTERN_C_END
*/
/* CFXMLParser.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: David Smith
*/
#include "CFUniChar.h"
#include "CFInternal.h"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
struct __CFXMLParser {
CFRuntimeBase _cfBase;
return newString;
}
-
+#pragma GCC diagnostic pop
*/
/* CFXMLParser.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
-/* CFXMLParser is deprecated. Clients should be aware of the fact that CFXMLParser has some serious
- deficiencies in terms of both performance and standards compliance and should migrate their XML
- parsing to NSXMLParser, NSXMLDocument, or other XML parsing technologies.
- */
+/* CFXMLParser is deprecated as of Mac OS X 10.8. The suggested replacements are the Foundation classes NSXMLParser and NSXMLDocument, or the libxml2 library. */
#if !defined(__COREFOUNDATION_CFXMLPARSER__)
#define __COREFOUNDATION_CFXMLPARSER__ 1
Currently not supported.
*/
-enum {
+typedef CF_OPTIONS(CFOptionFlags, CFXMLParserOptions) {
kCFXMLParserValidateDocument = (1UL << 0),
kCFXMLParserSkipMetaData = (1UL << 1),
kCFXMLParserReplacePhysicalEntities = (1UL << 2),
kCFXMLParserAllOptions = 0x00FFFFFF,
kCFXMLParserNoOptions = 0
};
-typedef CFOptionFlags CFXMLParserOptions;
/* This list is expected to grow */
-enum {
+typedef CF_OPTIONS(CFIndex, CFXMLParserStatusCode) {
kCFXMLStatusParseNotBegun = -2,
kCFXMLStatusParseInProgress = -1,
kCFXMLStatusParseSuccessful = 0,
kCFXMLErrorMalformedParsedCharacterData,
kCFXMLErrorNoData
};
-typedef CFIndex CFXMLParserStatusCode;
/* These functions are called as a parse progresses.
} CFXMLParserContext;
CF_EXPORT
-CFTypeID CFXMLParserGetTypeID(void);
+CFTypeID CFXMLParserGetTypeID(void) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Creates a parser which will parse the given data with the given options. xmlData may not be NULL.
dataSource should be the URL from which the data came, and may be NULL; it is used to resolve any
callBacks->endXMLStructure must all be non-NULL. context determines what if any info pointer is
passed to the callbacks as the parse progresses; context may be NULL. */
CF_EXPORT
-CFXMLParserRef CFXMLParserCreate(CFAllocatorRef allocator, CFDataRef xmlData, CFURLRef dataSource, CFOptionFlags parseOptions, CFIndex versionOfNodes, CFXMLParserCallBacks *callBacks, CFXMLParserContext *context);
+CFXMLParserRef CFXMLParserCreate(CFAllocatorRef allocator, CFDataRef xmlData, CFURLRef dataSource, CFOptionFlags parseOptions, CFIndex versionOfNodes, CFXMLParserCallBacks *callBacks, CFXMLParserContext *context) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Arguments as above, except that the data to be parsed is loaded directly
from dataSource. dataSource may not be NULL. */
CF_EXPORT
-CFXMLParserRef CFXMLParserCreateWithDataFromURL(CFAllocatorRef allocator, CFURLRef dataSource, CFOptionFlags parseOptions, CFIndex versionOfNodes, CFXMLParserCallBacks *callBacks, CFXMLParserContext *context);
+CFXMLParserRef CFXMLParserCreateWithDataFromURL(CFAllocatorRef allocator, CFURLRef dataSource, CFOptionFlags parseOptions, CFIndex versionOfNodes, CFXMLParserCallBacks *callBacks, CFXMLParserContext *context) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
CF_EXPORT
-void CFXMLParserGetContext(CFXMLParserRef parser, CFXMLParserContext *context);
+void CFXMLParserGetContext(CFXMLParserRef parser, CFXMLParserContext *context) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
CF_EXPORT
-void CFXMLParserGetCallBacks(CFXMLParserRef parser, CFXMLParserCallBacks *callBacks);
+void CFXMLParserGetCallBacks(CFXMLParserRef parser, CFXMLParserCallBacks *callBacks) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
CF_EXPORT
-CFURLRef CFXMLParserGetSourceURL(CFXMLParserRef parser);
+CFURLRef CFXMLParserGetSourceURL(CFXMLParserRef parser) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Returns the character index of the current parse location */
CF_EXPORT
-CFIndex CFXMLParserGetLocation(CFXMLParserRef parser);
+CFIndex CFXMLParserGetLocation(CFXMLParserRef parser) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Returns the line number of the current parse location */
CF_EXPORT
-CFIndex CFXMLParserGetLineNumber(CFXMLParserRef parser);
+CFIndex CFXMLParserGetLineNumber(CFXMLParserRef parser) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Returns the top-most object returned by the createXMLStructure callback */
CF_EXPORT
-void *CFXMLParserGetDocument(CFXMLParserRef parser);
+void *CFXMLParserGetDocument(CFXMLParserRef parser) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Get the status code or a user-readable description of the last error that occurred in a parse.
If no error has occurred, a null description string is returned. See the enum above for
possible status returns */
CF_EXPORT
-CFXMLParserStatusCode CFXMLParserGetStatusCode(CFXMLParserRef parser);
+CFXMLParserStatusCode CFXMLParserGetStatusCode(CFXMLParserRef parser) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
CF_EXPORT
-CFStringRef CFXMLParserCopyErrorDescription(CFXMLParserRef parser);
+CFStringRef CFXMLParserCopyErrorDescription(CFXMLParserRef parser) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Cause any in-progress parse to abort with the given error code and description. errorCode
must be positive, and errorDescription may not be NULL. Cannot be called asynchronously
(i.e. must be called from within a parser callback) */
CF_EXPORT
-void CFXMLParserAbort(CFXMLParserRef parser, CFXMLParserStatusCode errorCode, CFStringRef errorDescription);
+void CFXMLParserAbort(CFXMLParserRef parser, CFXMLParserStatusCode errorCode, CFStringRef errorDescription) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Starts a parse of the data the parser was created with; returns success or failure.
Upon success, use CFXMLParserGetDocument() to get the product of the parse. Upon
information about the error. It is an error to call CFXMLParserParse() while a
parse is already underway. */
CF_EXPORT
-Boolean CFXMLParserParse(CFXMLParserRef parser);
+Boolean CFXMLParserParse(CFXMLParserRef parser) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* These functions provide a higher-level interface. The XML data is parsed to a
special CFTree (an CFXMLTree) with known contexts and callbacks. See CFXMLNode.h
/* Parse to an CFXMLTreeRef. parseOptions are as above. versionOfNodes determines
what version CFXMLNodes are used to populate the tree. */
CF_EXPORT
-CFXMLTreeRef CFXMLTreeCreateFromData(CFAllocatorRef allocator, CFDataRef xmlData, CFURLRef dataSource, CFOptionFlags parseOptions, CFIndex versionOfNodes);
+CFXMLTreeRef CFXMLTreeCreateFromData(CFAllocatorRef allocator, CFDataRef xmlData, CFURLRef dataSource, CFOptionFlags parseOptions, CFIndex versionOfNodes) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* As above, with the additional by-reference pass of a CFDictionaryRef containing
various error information (see below). The caller is responsible for releasing the
returned dictionary. If the error dictionary is not desired, pass NULL. */
CF_EXPORT
-CFXMLTreeRef CFXMLTreeCreateFromDataWithError(CFAllocatorRef allocator, CFDataRef xmlData, CFURLRef dataSource, CFOptionFlags parseOptions, CFIndex versionOfNodes, CFDictionaryRef *errorDict);
+CFXMLTreeRef CFXMLTreeCreateFromDataWithError(CFAllocatorRef allocator, CFDataRef xmlData, CFURLRef dataSource, CFOptionFlags parseOptions, CFIndex versionOfNodes, CFDictionaryRef *errorDict) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Loads the data to be parsed directly from dataSource. Arguments as above. */
CF_EXPORT
-CFXMLTreeRef CFXMLTreeCreateWithDataFromURL(CFAllocatorRef allocator, CFURLRef dataSource, CFOptionFlags parseOptions, CFIndex versionOfNodes);
+CFXMLTreeRef CFXMLTreeCreateWithDataFromURL(CFAllocatorRef allocator, CFURLRef dataSource, CFOptionFlags parseOptions, CFIndex versionOfNodes) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Generate the XMLData (ready to be written to whatever permanent storage is to be
used) from an CFXMLTree. Will NOT regenerate entity references (except those
clients that wish this should walk the tree and re-insert any entity references
that should appear in the final output file. */
CF_EXPORT
-CFDataRef CFXMLTreeCreateXMLData(CFAllocatorRef allocator, CFXMLTreeRef xmlTree);
+CFDataRef CFXMLTreeCreateXMLData(CFAllocatorRef allocator, CFXMLTreeRef xmlTree) CF_DEPRECATED(10_0, 10_8, 2_0, 6_0);
/* Escaping and unescaping XML entities in CFStrings. The standard XML entities
are always replaced. */
*/
/* CFXMLPreferencesDomain.c
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
Responsibility: David Smith
*/
*/
/* CFXMLTree.c
- Copyright (c) 1999-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1999-2012, Apple Inc. All rights reserved.
Responsibility: David Smith
*/
#include "CFInternal.h"
#include <CoreFoundation/CFXMLParser.h>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
/*************/
/* CFXMLTree */
/*************/
}
}
-
+#pragma GCC diagnostic pop
*/
/* CoreFoundation.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !defined(__COREFOUNDATION_COREFOUNDATION__)
#include <CoreFoundation/CFURL.h>
#include <CoreFoundation/CFURLAccess.h>
#include <CoreFoundation/CFUUID.h>
+#include <CoreFoundation/CFUtilities.h>
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) || (TARGET_OS_EMBEDDED || TARGET_OS_IPHONE) || TARGET_OS_WIN32
#include <CoreFoundation/CFBundle.h>
*/
/* CoreFoundation_Prefix.h
- Copyright (c) 2005-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2005-2012, Apple Inc. All rights reserved.
*/
#define nil NULL
#endif
-#if DEPLOYMENT_TARGET_MACOSX && defined(__ppc__)
-#define SUPPORT_CFM 1
-#endif
+#define CRSetCrashLogMessage(A) do {} while (0)
+#define CRSetCrashLogMessage2(A) do {} while (0)
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#import <libkern/OSAtomic.h>
#import <pthread.h>
#endif
#define strtod_l(a,b,locale) strtod(a,b)
#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) strtoll(a,b,c)
#define strncasecmp_l(a, b, c, d) strncasecmp(a, b, c)
#define fprintf_l(a,locale,b,...) fprintf(a, b, __VA_ARGS__)
#endif
// The order of these includes is important
+#define FD_SETSIZE 1024
#include <winsock2.h>
#include <windows.h>
#include <pthread.h>
return _msize(memblock);
}
-#define mach_absolute_time() ((uint64_t)(CFAbsoluteTimeGetCurrent() * 1000000000.0))
+CF_INLINE uint64_t mach_absolute_time() {
+ LARGE_INTEGER count;
+ QueryPerformanceCounter(&count);
+ // mach_absolute_time is unsigned, but this function returns a signed value.
+ return (uint64_t)count.QuadPart;
+}
+
+CF_INLINE long long llabs(long long v) {
+ if (v < 0) return -v;
+ return v;
+}
#define strtod_l(a,b,locale) strtod(a,b)
#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_l(a, b, c, d) _strnicmp(a, b, c)
#define snprintf _snprintf
#endif
-// Need to use the _O_BINARY flag on Windows to get the correct behavior
-#if DEPLOYMENT_TARGET_WINDOWS
- #define CF_OPENFLGS (_O_BINARY|_O_NOINHERIT)
-#else
- #define CF_OPENFLGS (0)
-#endif
-
-#if DEPLOYMENT_TARGET_WINDOWS
-
-// These are replacements for pthread calls on Windows
-CF_EXPORT int _NS_pthread_main_np();
-CF_EXPORT int _NS_pthread_setspecific(pthread_key_t key, const void *val);
-CF_EXPORT void* _NS_pthread_getspecific(pthread_key_t key);
-CF_EXPORT int _NS_pthread_key_init_np(int key, void (*destructor)(void *));
-CF_EXPORT void _NS_pthread_setname_np(const char *name);
-
-// map use of pthread_set/getspecific to internal API
-#define pthread_setspecific _NS_pthread_setspecific
-#define pthread_getspecific _NS_pthread_getspecific
-#define pthread_key_init_np _NS_pthread_key_init_np
-#define pthread_main_np _NS_pthread_main_np
-#define pthread_setname_np _NS_pthread_setname_np
-#endif
-
-#if DEPLOYMENT_TARGET_WINDOWS
-// replacement for DISPATCH_QUEUE_OVERCOMMIT until we get a bug fix in dispatch on Windows
-// <rdar://problem/7923891> dispatch on Windows: Need queue_private.h
-#define DISPATCH_QUEUE_OVERCOMMIT 2
-#endif
-
#if DEPLOYMENT_TARGET_WINDOWS && defined(__cplusplus)
} // extern "C"
#endif
*/
/* ForFoundationOnly.h
- Copyright (c) 1998-2011, Apple Inc. All rights reserved.
+ Copyright (c) 1998-2012, Apple Inc. All rights reserved.
*/
#if !CF_BUILDING_CF && !NSBUILDINGFOUNDATION
#if DEPLOYMENT_TARGET_LINUX
#include <malloc.h>
-#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#include <malloc/malloc.h>
#endif
// ---- CFBundle material ----------------------------------------
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS
#include <CoreFoundation/CFBundlePriv.h>
CF_EXTERN_C_BEGIN
#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 bool __CFBinaryPlistGetOffsetForValueFromArray2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFIndex idx, uint64_t *offset, CFMutableDictionaryRef objects);
CF_EXPORT bool __CFBinaryPlistGetOffsetForValueFromDictionary3(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFTypeRef key, uint64_t *koffset, uint64_t *voffset, Boolean unused, CFMutableDictionaryRef objects);
CF_EXPORT bool __CFBinaryPlistCreateObject(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFPropertyListRef *plist);
-CF_EXPORT bool __CFBinaryPlistCreateObject2(const uint8_t *databytes, uint64_t datalen, uint64_t startOffset, const CFBinaryPlistTrailer *trailer, CFAllocatorRef allocator, CFOptionFlags mutabilityOption, CFMutableDictionaryRef objects, CFMutableSetRef set, CFIndex curDepth, CFPropertyListRef *plist);
CF_EXPORT CFIndex __CFBinaryPlistWriteToStream(CFPropertyListRef plist, CFTypeRef stream);
CF_EXPORT CFIndex __CFBinaryPlistWriteToStreamWithEstimate(CFPropertyListRef plist, CFTypeRef stream, uint64_t estimate); // will be removed soon
CF_EXPORT CFIndex __CFBinaryPlistWriteToStreamWithOptions(CFPropertyListRef plist, CFTypeRef stream, uint64_t estimate, CFOptionFlags options); // will be removed soon
CF_EXPORT void __CFURLSetReservedPtr(CFURLRef url, void *ptr);
CF_EXPORT CFStringEncoding _CFURLGetEncoding(CFURLRef url);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS
CF_EXPORT Boolean _CFRunLoopFinished(CFRunLoopRef rl, CFStringRef mode);
#endif
CF_EXPORT CFRange _CFDataFindBytes(CFDataRef data, CFDataRef dataToFind, CFRange searchRange, CFDataSearchFlags compareOptions);
-#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
+#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#if !defined(__CFReadTSR)
#include <mach/mach_time.h>
#define __CFReadTSR() mach_absolute_time()
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
- <string>6.7.2</string>
+ <string>6.8</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
include MakefileVersion
-MIN_MACOSX_VERSION=10.7
-MAX_MACOSX_VERSION=MAC_OS_X_VERSION_10_7
+MIN_MACOSX_VERSION=10.8
+MAX_MACOSX_VERSION=MAC_OS_X_VERSION_10_8
OBJECTS = $(patsubst %.c,%.o,$(wildcard *.c))
OBJECTS += CFBasicHash.o
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
-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
+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
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)
ARCHFLAGS=-arch i386 -arch x86_64
INSTALLNAME=/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation_$(STYLE)
-CC = /usr/bin/llvm-gcc
+CC = /usr/bin/clang
CFLAGS=-c -x c -pipe -std=gnu99 -Wmost -Wno-trigraphs -mmacosx-version-min=$(MIN_MACOSX_VERSION) -fconstant-cfstrings -fexceptions -DCF_BUILDING_CF=1 -DDEPLOYMENT_TARGET_MACOSX=1 -DMAC_OS_X_VERSION_MAX_ALLOWED=$(MAX_MACOSX_VERSION) -DU_SHOW_DRAFT_API=1 -DU_SHOW_CPLUSPLUS_API=0 -I$(OBJBASE) -DVERSION=$(VERSION) -include CoreFoundation_Prefix.h
MIN_MACOSX_VERSION=10.7
MAX_MACOSX_VERSION=MAC_OS_X_VERSION_10_7
-OBJECTS = CFCharacterSet.o CFPreferences.o CFApplicationPreferences.o CFXMLPreferencesDomain.o CFStringEncodingConverter.o CFUniChar.o CFArray.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 = 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))
-VERSION=635.21
+VERSION=744
/* TargetConditionals.h
- Copyright (c) 2010-2011, Apple Inc. All rights reserved.
+ Copyright (c) 2010-2012, Apple Inc. All rights reserved.
For CF on Linux ONLY
*/