/*
- * Copyright (c) 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*/
/* CFBag.c
- Copyright 1998-2008, Apple, Inc. All rights reserved.
+ Copyright (c) 1998-2011, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
Machine generated from Notes/HashingCode.template
*/
const CFBagKeyCallBacks kCFTypeBagKeyCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
const CFBagKeyCallBacks kCFCopyStringBagKeyCallBacks = {0, __CFStringCollectionCopy, __CFTypeCollectionRelease, CFCopyDescription, CFEqual, CFHash};
const CFBagValueCallBacks kCFTypeBagValueCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual};
+__private_extern__ const CFBagValueCallBacks kCFTypeBagValueCompactableCallBacks = {0, __CFTypeCollectionRetain, __CFTypeCollectionRelease, CFCopyDescription, CFEqual};
static const CFBagKeyCallBacks __kCFNullBagKeyCallBacks = {0, NULL, NULL, NULL, NULL, NULL};
static const CFBagValueCallBacks __kCFNullBagValueCallBacks = {0, NULL, NULL, NULL, NULL};
return __kCFBagTypeID;
}
-static uintptr_t __CFBagCallback(CFBasicHashRef ht, uint8_t op, uintptr_t a1, uintptr_t a2, CFBasicHashCallbacks *cb) {
- switch (op) {
- case kCFBasicHashCallbackOpCopyCallbacks: {
- CFBasicHashCallbacks *newcb = NULL;
- if (CF_IS_COLLECTABLE_ALLOCATOR((CFAllocatorRef)a1)) {
- newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(auto_zone(), 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, true, false);
- } else {
- newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate((CFAllocatorRef)a1, 10 * sizeof(void *), 0);
- }
- if (!newcb) HALT;
- memmove(newcb, (void *)cb, 10 * sizeof(void *));
- return (uintptr_t)newcb;
- }
- case kCFBasicHashCallbackOpFreeCallbacks: {
- if (CF_IS_COLLECTABLE_ALLOCATOR((CFAllocatorRef)a1)) {
- auto_zone_release(auto_zone(), cb);
- } else {
- CFAllocatorDeallocate((CFAllocatorRef)a1, cb);
- }
- return 0;
- }
- case kCFBasicHashCallbackOpRetainValue: {
- const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[0];
- if (NULL == value_retain) return a1;
- return (uintptr_t)INVOKE_CALLBACK2(value_retain, CFGetAllocator(ht), (const_any_pointer_t)a1);
- }
- case kCFBasicHashCallbackOpRetainKey: {
- const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[1];
- if (NULL == key_retain) return a1;
- return (uintptr_t)INVOKE_CALLBACK2(key_retain, CFGetAllocator(ht), (const_any_pointer_t)a1);
- }
- case kCFBasicHashCallbackOpReleaseValue: {
- void (*value_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[2];
- if (NULL != value_release) INVOKE_CALLBACK2(value_release, CFGetAllocator(ht), (const_any_pointer_t)a1);
- return 0;
- }
- case kCFBasicHashCallbackOpReleaseKey: {
- void (*key_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[3];
- if (NULL != key_release) INVOKE_CALLBACK2(key_release, CFGetAllocator(ht), (const_any_pointer_t)a1);
- return 0;
- }
- case kCFBasicHashCallbackOpValueEqual: {
- Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[4];
- if (NULL == value_equal) return (a1 == a2);
- return INVOKE_CALLBACK2(value_equal, (const_any_pointer_t)a1, (const_any_pointer_t)a2) ? 1 : 0;
- }
- case kCFBasicHashCallbackOpKeyEqual: {
- Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[5];
- if (NULL == key_equal) return (a1 == a2);
- return INVOKE_CALLBACK2(key_equal, (const_any_pointer_t)a1, (const_any_pointer_t)a2) ? 1 : 0;
- }
- case kCFBasicHashCallbackOpHashKey: {
- CFHashCode (*hash)(const_any_pointer_t) = (CFHashCode (*)(const_any_pointer_t))cb->context[6];
- if (NULL == hash) return a1;
- return (uintptr_t)INVOKE_CALLBACK1(hash, (const_any_pointer_t)a1);
- }
- case kCFBasicHashCallbackOpDescribeValue: {
- CFStringRef (*value_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[7];
- if (NULL == value_describe) return (uintptr_t)CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t)a1);
- return (uintptr_t)INVOKE_CALLBACK1(value_describe, (const_any_pointer_t)a1);
- }
- case kCFBasicHashCallbackOpDescribeKey: {
- CFStringRef (*key_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[8];
- if (NULL == key_describe) return (uintptr_t)CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t)a1);
- return (uintptr_t)INVOKE_CALLBACK1(key_describe, (const_any_pointer_t)a1);
+#define GCRETAIN(A, B) kCFTypeSetCallBacks.retain(A, B)
+#define GCRELEASE(A, B) kCFTypeSetCallBacks.release(A, B)
+
+static uintptr_t __CFBagStandardRetainValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
+ if (CFBasicHashGetSpecialBits(ht) & 0x0100) return stack_value;
+ return (CFBasicHashHasStrongValues(ht)) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)stack_value) : (uintptr_t)CFRetain((CFTypeRef)stack_value);
+}
+
+static uintptr_t __CFBagStandardRetainKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ if (CFBasicHashGetSpecialBits(ht) & 0x0001) return stack_key;
+ return (CFBasicHashHasStrongKeys(ht)) ? (uintptr_t)GCRETAIN(kCFAllocatorSystemDefault, (CFTypeRef)stack_key) : (uintptr_t)CFRetain((CFTypeRef)stack_key);
+}
+
+static void __CFBagStandardReleaseValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
+ if (CFBasicHashGetSpecialBits(ht) & 0x0200) return;
+ if (CFBasicHashHasStrongValues(ht)) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)stack_value); else CFRelease((CFTypeRef)stack_value);
+}
+
+static void __CFBagStandardReleaseKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ if (CFBasicHashGetSpecialBits(ht) & 0x0002) return;
+ if (CFBasicHashHasStrongKeys(ht)) GCRELEASE(kCFAllocatorSystemDefault, (CFTypeRef)stack_key); else CFRelease((CFTypeRef)stack_key);
+}
+
+static Boolean __CFBagStandardEquateValues(CFConstBasicHashRef ht, uintptr_t coll_value1, uintptr_t stack_value2) {
+ if (CFBasicHashGetSpecialBits(ht) & 0x0400) return coll_value1 == stack_value2;
+ return CFEqual((CFTypeRef)coll_value1, (CFTypeRef)stack_value2);
+}
+
+static Boolean __CFBagStandardEquateKeys(CFConstBasicHashRef ht, uintptr_t coll_key1, uintptr_t stack_key2) {
+ if (CFBasicHashGetSpecialBits(ht) & 0x0004) return coll_key1 == stack_key2;
+ return CFEqual((CFTypeRef)coll_key1, (CFTypeRef)stack_key2);
+}
+
+static uintptr_t __CFBagStandardHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ if (CFBasicHashGetSpecialBits(ht) & 0x0008) return stack_key;
+ return (uintptr_t)CFHash((CFTypeRef)stack_key);
+}
+
+static uintptr_t __CFBagStandardGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) {
+ return 0;
+}
+
+static CFStringRef __CFBagStandardCopyValueDescription(CFConstBasicHashRef ht, uintptr_t stack_value) {
+ if (CFBasicHashGetSpecialBits(ht) & 0x0800) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_value);
+ return CFCopyDescription((CFTypeRef)stack_value);
+}
+
+static CFStringRef __CFBagStandardCopyKeyDescription(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ if (CFBasicHashGetSpecialBits(ht) & 0x0010) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (void *)stack_key);
+ return CFCopyDescription((CFTypeRef)stack_key);
+}
+
+static CFBasicHashCallbacks *__CFBagStandardCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb);
+static void __CFBagStandardFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb);
+
+static const CFBasicHashCallbacks CFBagStandardCallbacks = {
+ __CFBagStandardCopyCallbacks,
+ __CFBagStandardFreeCallbacks,
+ __CFBagStandardRetainValue,
+ __CFBagStandardRetainKey,
+ __CFBagStandardReleaseValue,
+ __CFBagStandardReleaseKey,
+ __CFBagStandardEquateValues,
+ __CFBagStandardEquateKeys,
+ __CFBagStandardHashKey,
+ __CFBagStandardGetIndirectKey,
+ __CFBagStandardCopyValueDescription,
+ __CFBagStandardCopyKeyDescription
+};
+
+static CFBasicHashCallbacks *__CFBagStandardCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) {
+ return (CFBasicHashCallbacks *)&CFBagStandardCallbacks;
+}
+
+static void __CFBagStandardFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) {
+}
+
+
+static CFBasicHashCallbacks *__CFBagCopyCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) {
+ CFBasicHashCallbacks *newcb = NULL;
+ if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+ newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(objc_collectableZone(), sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, false, false);
+ } else {
+ newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0);
}
+ if (!newcb) HALT;
+ memmove(newcb, (void *)cb, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *));
+ return newcb;
+}
+
+static void __CFBagFreeCallbacks(CFConstBasicHashRef ht, CFAllocatorRef allocator, CFBasicHashCallbacks *cb) {
+ if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
+ } else {
+ CFAllocatorDeallocate(allocator, cb);
}
+}
+
+static uintptr_t __CFBagRetainValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
+ const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
+ const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[0];
+ if (NULL == value_retain) return stack_value;
+ return (uintptr_t)INVOKE_CALLBACK2(value_retain, CFGetAllocator(ht), (const_any_pointer_t)stack_value);
+}
+
+static uintptr_t __CFBagRetainKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
+ const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = (const_any_pointer_t (*)(CFAllocatorRef, const_any_pointer_t))cb->context[1];
+ if (NULL == key_retain) return stack_key;
+ return (uintptr_t)INVOKE_CALLBACK2(key_retain, CFGetAllocator(ht), (const_any_pointer_t)stack_key);
+}
+
+static void __CFBagReleaseValue(CFConstBasicHashRef ht, uintptr_t stack_value) {
+ const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
+ void (*value_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[2];
+ if (NULL != value_release) INVOKE_CALLBACK2(value_release, CFGetAllocator(ht), (const_any_pointer_t) stack_value);
+}
+
+static void __CFBagReleaseKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
+ void (*key_release)(CFAllocatorRef, const_any_pointer_t) = (void (*)(CFAllocatorRef, const_any_pointer_t))cb->context[3];
+ if (NULL != key_release) INVOKE_CALLBACK2(key_release, CFGetAllocator(ht), (const_any_pointer_t) stack_key);
+}
+
+static Boolean __CFBagEquateValues(CFConstBasicHashRef ht, uintptr_t coll_value1, uintptr_t stack_value2) {
+ const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
+ Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[4];
+ if (NULL == value_equal) return (coll_value1 == stack_value2);
+ return INVOKE_CALLBACK2(value_equal, (const_any_pointer_t) coll_value1, (const_any_pointer_t) stack_value2) ? 1 : 0;
+}
+
+static Boolean __CFBagEquateKeys(CFConstBasicHashRef ht, uintptr_t coll_key1, uintptr_t stack_key2) {
+ const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
+ Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = (Boolean (*)(const_any_pointer_t, const_any_pointer_t))cb->context[5];
+ if (NULL == key_equal) return (coll_key1 == stack_key2);
+ return INVOKE_CALLBACK2(key_equal, (const_any_pointer_t) coll_key1, (const_any_pointer_t) stack_key2) ? 1 : 0;
+}
+
+static uintptr_t __CFBagHashKey(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
+ CFHashCode (*hash)(const_any_pointer_t) = (CFHashCode (*)(const_any_pointer_t))cb->context[6];
+ if (NULL == hash) return stack_key;
+ return (uintptr_t)INVOKE_CALLBACK1(hash, (const_any_pointer_t) stack_key);
+}
+
+static uintptr_t __CFBagGetIndirectKey(CFConstBasicHashRef ht, uintptr_t coll_value) {
return 0;
}
-static CFBasicHashRef __CFBagCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) {
+static CFStringRef __CFBagCopyValueDescription(CFConstBasicHashRef ht, uintptr_t stack_value) {
+ const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
+ CFStringRef (*value_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[8];
+ if (NULL == value_describe) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t) stack_value);
+ return (CFStringRef)INVOKE_CALLBACK1(value_describe, (const_any_pointer_t) stack_value);
+}
- CFBasicHashCallbacks *cb = NULL;
+static CFStringRef __CFBagCopyKeyDescription(CFConstBasicHashRef ht, uintptr_t stack_key) {
+ const CFBasicHashCallbacks *cb = CFBasicHashGetCallbacks(ht);
+ CFStringRef (*key_describe)(const_any_pointer_t) = (CFStringRef (*)(const_any_pointer_t))cb->context[9];
+ if (NULL == key_describe) return CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<%p>"), (const_any_pointer_t) stack_key);
+ return (CFStringRef)INVOKE_CALLBACK1(key_describe, (const_any_pointer_t) stack_key);
+}
+
+static CFBasicHashRef __CFBagCreateGeneric(CFAllocatorRef allocator, const CFHashKeyCallBacks *keyCallBacks, const CFHashValueCallBacks *valueCallBacks, Boolean useValueCB) {
CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing
flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0);
+ CFBasicHashCallbacks *cb = NULL;
+ Boolean std_cb = false;
+ uint16_t specialBits = 0;
const_any_pointer_t (*key_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
void (*key_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
const_any_pointer_t (*value_retain)(CFAllocatorRef, const_any_pointer_t) = NULL;
void (*value_release)(CFAllocatorRef, const_any_pointer_t) = NULL;
- Boolean std_cb = false;
- if ((NULL == keyCallBacks || (keyCallBacks && 0 == memcmp(&__kCFNullBagKeyCallBacks, keyCallBacks, sizeof(__kCFNullBagKeyCallBacks))))
- && (!useValueCB || (NULL == valueCallBacks || (valueCallBacks && 0 == memcmp(&__kCFNullBagValueCallBacks, valueCallBacks, sizeof(__kCFNullBagValueCallBacks)))))) {
- cb = (CFBasicHashCallbacks *)& CFBasicHashNullCallbacks;
- } else if ((&kCFTypeBagKeyCallBacks == keyCallBacks || (keyCallBacks && 0 == memcmp(&kCFTypeBagKeyCallBacks, keyCallBacks, sizeof(kCFTypeBagKeyCallBacks))))
- && (!useValueCB || (&kCFTypeBagValueCallBacks == valueCallBacks || (valueCallBacks && 0 == memcmp(&kCFTypeBagValueCallBacks, valueCallBacks, sizeof(kCFTypeBagValueCallBacks)))))) {
- std_cb = true;
- cb = (CFBasicHashCallbacks *)& CFBasicHashStandardCallbacks;
- } else {
+
+ if ((NULL == keyCallBacks || 0 == keyCallBacks->version) && (!useValueCB || NULL == valueCallBacks || 0 == valueCallBacks->version)) {
+ Boolean keyRetainNull = NULL == keyCallBacks || NULL == keyCallBacks->retain;
+ Boolean keyReleaseNull = NULL == keyCallBacks || NULL == keyCallBacks->release;
+ Boolean keyEquateNull = NULL == keyCallBacks || NULL == keyCallBacks->equal;
+ Boolean keyHashNull = NULL == keyCallBacks || NULL == keyCallBacks->hash;
+ Boolean keyDescribeNull = NULL == keyCallBacks || NULL == keyCallBacks->copyDescription;
+
+ Boolean valueRetainNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->retain)) || (!useValueCB && keyRetainNull);
+ Boolean valueReleaseNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->release)) || (!useValueCB && keyReleaseNull);
+ Boolean valueEquateNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->equal)) || (!useValueCB && keyEquateNull);
+ Boolean valueDescribeNull = (useValueCB && (NULL == valueCallBacks || NULL == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeNull);
+
+ Boolean keyRetainStd = keyRetainNull || __CFTypeCollectionRetain == keyCallBacks->retain;
+ Boolean keyReleaseStd = keyReleaseNull || __CFTypeCollectionRelease == keyCallBacks->release;
+ Boolean keyEquateStd = keyEquateNull || CFEqual == keyCallBacks->equal;
+ Boolean keyHashStd = keyHashNull || CFHash == keyCallBacks->hash;
+ Boolean keyDescribeStd = keyDescribeNull || CFCopyDescription == keyCallBacks->copyDescription;
+
+ Boolean valueRetainStd = (useValueCB && (valueRetainNull || __CFTypeCollectionRetain == valueCallBacks->retain)) || (!useValueCB && keyRetainStd);
+ Boolean valueReleaseStd = (useValueCB && (valueReleaseNull || __CFTypeCollectionRelease == valueCallBacks->release)) || (!useValueCB && keyReleaseStd);
+ Boolean valueEquateStd = (useValueCB && (valueEquateNull || CFEqual == valueCallBacks->equal)) || (!useValueCB && keyEquateStd);
+ Boolean valueDescribeStd = (useValueCB && (valueDescribeNull || CFCopyDescription == valueCallBacks->copyDescription)) || (!useValueCB && keyDescribeStd);
+
+ if (keyRetainStd && keyReleaseStd && keyEquateStd && keyHashStd && keyDescribeStd && valueRetainStd && valueReleaseStd && valueEquateStd && valueDescribeStd) {
+ cb = (CFBasicHashCallbacks *)&CFBagStandardCallbacks;
+ if (!(keyRetainNull || keyReleaseNull || keyEquateNull || keyHashNull || keyDescribeNull || valueRetainNull || valueReleaseNull || valueEquateNull || valueDescribeNull)) {
+ std_cb = true;
+ } else {
+ // just set these to tickle the GC Strong logic below in a way that mimics past practice
+ key_retain = keyCallBacks ? keyCallBacks->retain : NULL;
+ key_release = keyCallBacks ? keyCallBacks->release : NULL;
+ if (useValueCB) {
+ value_retain = valueCallBacks ? valueCallBacks->retain : NULL;
+ value_release = valueCallBacks ? valueCallBacks->release : NULL;
+ } else {
+ value_retain = key_retain;
+ value_release = key_release;
+ }
+ }
+ if (keyRetainNull) specialBits |= 0x0001;
+ if (keyReleaseNull) specialBits |= 0x0002;
+ if (keyEquateNull) specialBits |= 0x0004;
+ if (keyHashNull) specialBits |= 0x0008;
+ if (keyDescribeNull) specialBits |= 0x0010;
+ if (valueRetainNull) specialBits |= 0x0100;
+ if (valueReleaseNull) specialBits |= 0x0200;
+ if (valueEquateNull) specialBits |= 0x0400;
+ if (valueDescribeNull) specialBits |= 0x0800;
+ }
+ }
+
+ if (!cb) {
Boolean (*key_equal)(const_any_pointer_t, const_any_pointer_t) = NULL;
Boolean (*value_equal)(const_any_pointer_t, const_any_pointer_t) = NULL;
CFStringRef (*key_describe)(const_any_pointer_t) = NULL;
value_describe = key_describe;
}
hash_key = keyCallBacks ? keyCallBacks->hash : NULL;
- FAULT_CALLBACK((void **)&key_retain);
- FAULT_CALLBACK((void **)&key_release);
- FAULT_CALLBACK((void **)&value_retain);
- FAULT_CALLBACK((void **)&value_release);
- FAULT_CALLBACK((void **)&key_equal);
- FAULT_CALLBACK((void **)&value_equal);
- FAULT_CALLBACK((void **)&key_describe);
- FAULT_CALLBACK((void **)&value_describe);
- FAULT_CALLBACK((void **)&hash_key);
CFBasicHashCallbacks *newcb = NULL;
if (CF_IS_COLLECTABLE_ALLOCATOR(allocator)) {
- newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(auto_zone(), 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, true, false);
+ newcb = (CFBasicHashCallbacks *)auto_zone_allocate_object(objc_collectableZone(), sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), AUTO_MEMORY_UNSCANNED, false, false);
} else {
- newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, 10 * sizeof(void *), 0);
+ newcb = (CFBasicHashCallbacks *)CFAllocatorAllocate(allocator, sizeof(CFBasicHashCallbacks) + 10 * sizeof(void *), 0);
}
if (!newcb) HALT;
- newcb->func = (CFBasicHashCallbackType)__CFBagCallback;
+ newcb->copyCallbacks = __CFBagCopyCallbacks;
+ newcb->freeCallbacks = __CFBagFreeCallbacks;
+ newcb->retainValue = __CFBagRetainValue;
+ newcb->retainKey = __CFBagRetainKey;
+ newcb->releaseValue = __CFBagReleaseValue;
+ newcb->releaseKey = __CFBagReleaseKey;
+ newcb->equateValues = __CFBagEquateValues;
+ newcb->equateKeys = __CFBagEquateKeys;
+ newcb->hashKey = __CFBagHashKey;
+ newcb->getIndirectKey = __CFBagGetIndirectKey;
+ newcb->copyValueDescription = __CFBagCopyValueDescription;
+ newcb->copyKeyDescription = __CFBagCopyKeyDescription;
newcb->context[0] = (uintptr_t)value_retain;
newcb->context[1] = (uintptr_t)key_retain;
newcb->context[2] = (uintptr_t)value_release;
newcb->context[4] = (uintptr_t)value_equal;
newcb->context[5] = (uintptr_t)key_equal;
newcb->context[6] = (uintptr_t)hash_key;
- newcb->context[7] = (uintptr_t)value_describe;
- newcb->context[8] = (uintptr_t)key_describe;
+ newcb->context[8] = (uintptr_t)value_describe;
+ newcb->context[9] = (uintptr_t)key_describe;
cb = newcb;
}
if (std_cb || key_retain != NULL || key_release != NULL) {
flags |= kCFBasicHashStrongKeys;
}
+#if CFDictionary
+ if (valueCallBacks == &kCFTypeDictionaryValueCompactableCallBacks) {
+ // Foundation allocated collections will have compactable values
+ flags |= kCFBasicHashCompactableValues;
+ }
+#endif
}
- return CFBasicHashCreate(allocator, flags, cb);
+ CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb);
+ CFBasicHashSetSpecialBits(ht, specialBits);
+ return ht;
+}
+
+#if CFDictionary
+__private_extern__ CFHashRef __CFBagCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, const_any_pointer_t *vlist, CFIndex numValues) {
+#endif
+#if CFSet || CFBag
+__private_extern__ CFHashRef __CFBagCreateTransfer(CFAllocatorRef allocator, const_any_pointer_t *klist, CFIndex numValues) {
+ const_any_pointer_t *vlist = klist;
+#endif
+ CFTypeID typeID = CFBagGetTypeID();
+ CFAssert2(0 <= numValues, __kCFLogAssertion, "%s(): numValues (%ld) cannot be less than zero", __PRETTY_FUNCTION__, numValues);
+ CFOptionFlags flags = kCFBasicHashLinearHashing; // kCFBasicHashExponentialHashing
+ flags |= (CFDictionary ? kCFBasicHashHasKeys : 0) | (CFBag ? kCFBasicHashHasCounts : 0);
+ CFBasicHashCallbacks *cb = (CFBasicHashCallbacks *)&CFBagStandardCallbacks;
+ CFBasicHashRef ht = CFBasicHashCreate(allocator, flags, cb);
+ CFBasicHashSetSpecialBits(ht, 0x0303);
+ if (0 < numValues) CFBasicHashSetCapacity(ht, numValues);
+ for (CFIndex idx = 0; idx < numValues; idx++) {
+ CFBasicHashAddValue(ht, (uintptr_t)klist[idx], (uintptr_t)vlist[idx]);
+ }
+ CFBasicHashSetSpecialBits(ht, 0x0000);
+ CFBasicHashMakeImmutable(ht);
+ *(uintptr_t *)ht = __CFISAForTypeID(typeID);
+ _CFRuntimeSetInstanceTypeID(ht, typeID);
+ if (__CFOASafe) __CFSetLastAllocationEventName(ht, "CFBag (immutable)");
+ return (CFHashRef)ht;
}
#if CFDictionary
}
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_FUNCDISPATCH2(__kCFBagTypeID, Boolean, hc, "__getValue:forKey:", (any_t *)value, key);
+ if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, Boolean, hc, "__getValue:forObj:", (any_t *)value, key);
__CFGenericValidateType(hc, __kCFBagTypeID);
CFBasicHashBucket bkt = CFBasicHashFindBucket((CFBasicHashRef)hc, (uintptr_t)key);
if (0 < bkt.count) {
__CFGenericValidateType(hc, __kCFBagTypeID);
if (kCFUseCollectableAllocator) {
CFOptionFlags flags = CFBasicHashGetFlags((CFBasicHashRef)hc);
- __block const_any_pointer_t *keys = keybuf, *values = valuebuf;
+ __block const_any_pointer_t *keys = keybuf;
+ __block const_any_pointer_t *values = valuebuf;
CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
for (CFIndex cnt = bkt.count; cnt--;) {
if (keybuf && (flags & kCFBasicHashStrongKeys)) { __CFAssignWithWriteBarrier((void **)keys, (void *)bkt.weak_key); keys++; }
return (Boolean)true;
});
} else {
- CFBasicHashGetElements((CFBasicHashRef)hc, CFBagGetCount(hc), (uintptr_t *)valuebuf, NULL, (uintptr_t *)keybuf, NULL);
+ CFBasicHashGetElements((CFBasicHashRef)hc, CFBagGetCount(hc), (uintptr_t *)valuebuf, (uintptr_t *)keybuf);
}
}
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_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "__apply:context:", applier, context);
+ if (CFSet) CF_OBJC_FUNCDISPATCH2(__kCFBagTypeID, void, hc, "__applyValues:context:", applier, context);
__CFGenericValidateType(hc, __kCFBagTypeID);
CFBasicHashApply((CFBasicHashRef)hc, ^(CFBasicHashBucket bkt) {
#if CFDictionary
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 (CFSet) CF_OBJC_FUNCDISPATCH1(__kCFBagTypeID, void, hc, "setObject:", key);
__CFGenericValidateType(hc, __kCFBagTypeID);
CFAssert2(CFBasicHashIsMutable((CFBasicHashRef)hc), __kCFLogAssertion, "%s(): immutable collection %p passed to mutating operation", __PRETTY_FUNCTION__, hc);
if (!CFBasicHashIsMutable((CFBasicHashRef)hc)) {