2  * Copyright (c) 2009 Apple Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  25         Copyright (c) 1998-2009, Apple Inc. All rights reserved. 
  26         Responsibility: Christopher Kane 
  29 #include <CoreFoundation/CFArray.h> 
  30 #include "CFStorage.h" 
  31 #include <CoreFoundation/CFPriv.h> 
  32 #include "CFInternal.h" 
  34 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED 
  35 #include <libkern/OSAtomic.h> 
  38 __private_extern__ 
void _CFStorageSetWeak(CFStorageRef storage
); 
  40 const CFArrayCallBacks kCFTypeArrayCallBacks 
= {0, __CFTypeCollectionRetain
, __CFTypeCollectionRelease
, CFCopyDescription
, CFEqual
}; 
  41 static const CFArrayCallBacks __kCFNullArrayCallBacks 
= {0, NULL
, NULL
, NULL
, NULL
}; 
  43 struct __CFArrayBucket 
{ 
  48     __CF_MAX_BUCKETS_PER_DEQUE 
= 262140 
  51 CF_INLINE CFIndex 
__CFArrayDequeRoundUpCapacity(CFIndex capacity
) { 
  52     if (capacity 
< 4) return 4; 
  53     return __CFMin((1 << flsl(capacity
)), __CF_MAX_BUCKETS_PER_DEQUE
); 
  56 struct __CFArrayDeque 
{ 
  61     uint32_t _pad
;   // GC:  pointers must be 8-byte aligned for the collector to find them. 
  63     /* struct __CFArrayBucket buckets follow here */ 
  68     CFIndex _count
;             /* number of objects */ 
  70     int32_t _mutInProgress
; 
  71     void *_store
;           /* can be NULL when MutableDeque */ 
  76     __kCFArrayImmutable 
= 0, 
  82     __kCFArrayHasNullCallBacks 
= 0, 
  83     __kCFArrayHasCFTypeCallBacks 
= 1, 
  84     __kCFArrayHasCustomCallBacks 
= 3    /* callbacks are at end of header */ 
  88     Bits 4 & 5 are reserved for GC use. 
  89     Bit 4, if set, indicates that the array is weak. 
  90     Bit 5 marks whether finalization has occured and, thus, whether to continue to do special retain/release processing of elements. 
  93 CF_INLINE 
bool isStrongMemory(CFTypeRef collection
) { 
  94     return __CFBitfieldGetValue(((const CFRuntimeBase 
*)collection
)->_cfinfo
[CF_INFO_BITS
], 4, 4) == 0; 
  97 CF_INLINE 
bool isWeakMemory(CFTypeRef collection
) { 
  98     return __CFBitfieldGetValue(((const CFRuntimeBase 
*)collection
)->_cfinfo
[CF_INFO_BITS
], 4, 4) != 0; 
 101 CF_INLINE 
bool hasBeenFinalized(CFTypeRef collection
) { 
 102     return __CFBitfieldGetValue(((const CFRuntimeBase 
*)collection
)->_cfinfo
[CF_INFO_BITS
], 5, 5) != 0; 
 105 CF_INLINE 
void markFinalized(CFTypeRef collection
) { 
 106     __CFBitfieldSetValue(((CFRuntimeBase 
*)collection
)->_cfinfo
[CF_INFO_BITS
], 5, 5, 1); 
 109 CF_INLINE CFIndex 
__CFArrayGetType(CFArrayRef array
) { 
 110     return __CFBitfieldGetValue(((const CFRuntimeBase 
*)array
)->_cfinfo
[CF_INFO_BITS
], 1, 0); 
 113 CF_INLINE CFIndex 
__CFArrayGetSizeOfType(CFIndex t
) { 
 115         size 
+= sizeof(struct __CFArray
); 
 116     if (__CFBitfieldGetValue(t
, 3, 2) == __kCFArrayHasCustomCallBacks
) { 
 117         size 
+= sizeof(CFArrayCallBacks
); 
 122 CF_INLINE CFIndex 
__CFArrayGetCount(CFArrayRef array
) { 
 123     return array
->_count
; 
 126 CF_INLINE 
void __CFArraySetCount(CFArrayRef array
, CFIndex v
) { 
 127     ((struct __CFArray 
*)array
)->_count 
= v
; 
 130 /* Only applies to immutable and mutable-deque-using arrays; 
 131  * Returns the bucket holding the left-most real value in the latter case. */ 
 132 CF_INLINE 
struct __CFArrayBucket 
*__CFArrayGetBucketsPtr(CFArrayRef array
) { 
 133     switch (__CFArrayGetType(array
)) { 
 134     case __kCFArrayImmutable
: 
 135         return (struct __CFArrayBucket 
*)((uint8_t *)array 
+ __CFArrayGetSizeOfType(((CFRuntimeBase 
*)array
)->_cfinfo
[CF_INFO_BITS
])); 
 136     case __kCFArrayDeque
: { 
 137         struct __CFArrayDeque 
*deque 
= (struct __CFArrayDeque 
*)array
->_store
; 
 138         return (struct __CFArrayBucket 
*)((uint8_t *)deque 
+ sizeof(struct __CFArrayDeque
) + deque
->_leftIdx 
* sizeof(struct __CFArrayBucket
)); 
 144 /* This shouldn't be called if the array count is 0. */ 
 145 CF_INLINE 
struct __CFArrayBucket 
*__CFArrayGetBucketAtIndex(CFArrayRef array
, CFIndex idx
) { 
 146     switch (__CFArrayGetType(array
)) { 
 147     case __kCFArrayImmutable
: 
 148     case __kCFArrayDeque
: 
 149         return __CFArrayGetBucketsPtr(array
) + idx
; 
 150     case __kCFArrayStorage
: { 
 151         CFStorageRef store 
= (CFStorageRef
)array
->_store
; 
 152         return (struct __CFArrayBucket 
*)CFStorageGetValueAtIndex(store
, idx
, NULL
); 
 158 CF_INLINE CFArrayCallBacks 
*__CFArrayGetCallBacks(CFArrayRef array
) { 
 159     CFArrayCallBacks 
*result 
= NULL
; 
 160     switch (__CFBitfieldGetValue(((const CFRuntimeBase 
*)array
)->_cfinfo
[CF_INFO_BITS
], 3, 2)) { 
 161     case __kCFArrayHasNullCallBacks
: 
 162         return (CFArrayCallBacks 
*)&__kCFNullArrayCallBacks
; 
 163     case __kCFArrayHasCFTypeCallBacks
: 
 164         return (CFArrayCallBacks 
*)&kCFTypeArrayCallBacks
; 
 165     case __kCFArrayHasCustomCallBacks
: 
 168     switch (__CFArrayGetType(array
)) { 
 169     case __kCFArrayImmutable
: 
 170         result 
= (CFArrayCallBacks 
*)((uint8_t *)array 
+ sizeof(struct __CFArray
)); 
 172     case __kCFArrayDeque
: 
 173     case __kCFArrayStorage
: 
 174         result 
= (CFArrayCallBacks 
*)((uint8_t *)array 
+ sizeof(struct __CFArray
)); 
 180 CF_INLINE 
bool __CFArrayCallBacksMatchNull(const CFArrayCallBacks 
*c
) { 
 182         (c
->retain 
== __kCFNullArrayCallBacks
.retain 
&& 
 183          c
->release 
== __kCFNullArrayCallBacks
.release 
&& 
 184          c
->copyDescription 
== __kCFNullArrayCallBacks
.copyDescription 
&& 
 185          c
->equal 
== __kCFNullArrayCallBacks
.equal
)); 
 188 CF_INLINE 
bool __CFArrayCallBacksMatchCFType(const CFArrayCallBacks 
*c
) { 
 189     return (&kCFTypeArrayCallBacks 
== c 
|| 
 190         (c
->retain 
== kCFTypeArrayCallBacks
.retain 
&& 
 191          c
->release 
== kCFTypeArrayCallBacks
.release 
&& 
 192          c
->copyDescription 
== kCFTypeArrayCallBacks
.copyDescription 
&& 
 193          c
->equal 
== kCFTypeArrayCallBacks
.equal
)); 
 197 #define CHECK_FOR_MUTATION(A) do { if ((A)->_mutInProgress) CFLog(3, CFSTR("*** %s: function called while the array (%p) is being mutated in this or another thread"), __PRETTY_FUNCTION__, (A)); } while (0) 
 198 #define BEGIN_MUTATION(A) do { OSAtomicAdd32Barrier(1, &((struct __CFArray *)(A))->_mutInProgress); } while (0) 
 199 #define END_MUTATION(A) do { OSAtomicAdd32Barrier(-1, &((struct __CFArray *)(A))->_mutInProgress); } while (0) 
 201 #define CHECK_FOR_MUTATION(A) do { } while (0) 
 202 #define BEGIN_MUTATION(A) do { } while (0) 
 203 #define END_MUTATION(A) do { } while (0) 
 206 struct _releaseContext 
{ 
 207     void (*release
)(CFAllocatorRef
, const void *); 
 208     CFAllocatorRef allocator
;  
 211 static void __CFArrayStorageRelease(const void *itemptr
, void *context
) { 
 212     struct _releaseContext 
*rc 
= (struct _releaseContext 
*)context
; 
 213     INVOKE_CALLBACK2(rc
->release
, rc
->allocator
, *(const void **)itemptr
); 
 214     *(const void **)itemptr 
= NULL
; // GC:  clear item to break strong reference. 
 217 static void __CFArrayReleaseValues(CFArrayRef array
, CFRange range
, bool releaseStorageIfPossible
) { 
 218     const CFArrayCallBacks 
*cb 
= __CFArrayGetCallBacks(array
); 
 219     CFAllocatorRef allocator
; 
 221     switch (__CFArrayGetType(array
)) { 
 222     case __kCFArrayImmutable
: 
 223         if (NULL 
!= cb
->release 
&& 0 < range
.length 
&& !hasBeenFinalized(array
)) { 
 224             // if we've been finalized then we know that 
 225             //   1) we're using the standard callback on GC memory 
 226             //   2) the slots don't' need to be zeroed 
 227             struct __CFArrayBucket 
*buckets 
= __CFArrayGetBucketsPtr(array
); 
 228             allocator 
= __CFGetAllocator(array
); 
 229             for (idx 
= 0; idx 
< range
.length
; idx
++) { 
 230                 INVOKE_CALLBACK2(cb
->release
, allocator
, buckets
[idx 
+ range
.location
]._item
); 
 231                 buckets
[idx 
+ range
.location
]._item 
= NULL
; // GC:  break strong reference. 
 235     case __kCFArrayDeque
: { 
 236         struct __CFArrayDeque 
*deque 
= (struct __CFArrayDeque 
*)array
->_store
; 
 237         if (0 < range
.length 
&& NULL 
!= deque 
&& !hasBeenFinalized(array
)) { 
 238             struct __CFArrayBucket 
*buckets 
= __CFArrayGetBucketsPtr(array
); 
 239             if (NULL 
!= cb
->release
) { 
 240                 allocator 
= __CFGetAllocator(array
); 
 241                 for (idx 
= 0; idx 
< range
.length
; idx
++) { 
 242                     INVOKE_CALLBACK2(cb
->release
, allocator
, buckets
[idx 
+ range
.location
]._item
); 
 243                     buckets
[idx 
+ range
.location
]._item 
= NULL
; // GC:  break strong reference. 
 246                 for (idx 
= 0; idx 
< range
.length
; idx
++) { 
 247                     buckets
[idx 
+ range
.location
]._item 
= NULL
; // GC:  break strong reference. 
 251         if (releaseStorageIfPossible 
&& 0 == range
.location 
&& __CFArrayGetCount(array
) == range
.length
) { 
 252             allocator 
= __CFGetAllocator(array
); 
 253             if (NULL 
!= deque
) _CFAllocatorDeallocateGC(allocator
, deque
); 
 254             __CFArraySetCount(array
, 0);  // GC: _count == 0 ==> _store == NULL. 
 255             ((struct __CFArray 
*)array
)->_store 
= NULL
; 
 259     case __kCFArrayStorage
: { 
 260         CFStorageRef store 
= (CFStorageRef
)array
->_store
; 
 261         if (NULL 
!= cb
->release 
&& 0 < range
.length 
&& !hasBeenFinalized(array
)) { 
 262             struct _releaseContext context
; 
 263             allocator 
= __CFGetAllocator(array
); 
 264             context
.release 
= cb
->release
; 
 265             context
.allocator 
= allocator
; 
 266             CFStorageApplyFunction(store
, range
, __CFArrayStorageRelease
, &context
); 
 268         if (releaseStorageIfPossible 
&& 0 == range
.location 
&& __CFArrayGetCount(array
) == range
.length
) { 
 270             __CFArraySetCount(array
, 0);  // GC: _count == 0 ==> _store == NULL. 
 271             ((struct __CFArray 
*)array
)->_store 
= NULL
; 
 272             __CFBitfieldSetValue(((CFRuntimeBase 
*)array
)->_cfinfo
[CF_INFO_BITS
], 1, 0, __kCFArrayDeque
); 
 280 CF_INLINE 
void __CFArrayValidateRange(CFArrayRef array
, CFRange range
, const char *func
) { 
 281     CFAssert3(0 <= range
.location 
&& range
.location 
<= CFArrayGetCount(array
), __kCFLogAssertion
, "%s(): range.location index (%d) out of bounds (0, %d)", func
, range
.location
, CFArrayGetCount(array
)); 
 282     CFAssert2(0 <= range
.length
, __kCFLogAssertion
, "%s(): range.length (%d) cannot be less than zero", func
, range
.length
); 
 283     CFAssert3(range
.location 
+ range
.length 
<= CFArrayGetCount(array
), __kCFLogAssertion
, "%s(): ending index (%d) out of bounds (0, %d)", func
, range
.location 
+ range
.length
, CFArrayGetCount(array
)); 
 286 #define __CFArrayValidateRange(a,r,f) 
 289 static Boolean 
__CFArrayEqual(CFTypeRef cf1
, CFTypeRef cf2
) { 
 290     CFArrayRef array1 
= (CFArrayRef
)cf1
; 
 291     CFArrayRef array2 
= (CFArrayRef
)cf2
; 
 292     const CFArrayCallBacks 
*cb1
, *cb2
; 
 294     if (array1 
== array2
) return true; 
 295     cnt 
= __CFArrayGetCount(array1
); 
 296     if (cnt 
!= __CFArrayGetCount(array2
)) return false; 
 297     cb1 
= __CFArrayGetCallBacks(array1
); 
 298     cb2 
= __CFArrayGetCallBacks(array2
); 
 299     if (cb1
->equal 
!= cb2
->equal
) return false; 
 300     if (0 == cnt
) return true;  /* after function comparison! */ 
 301     for (idx 
= 0; idx 
< cnt
; idx
++) { 
 302         const void *val1 
= __CFArrayGetBucketAtIndex(array1
, idx
)->_item
; 
 303         const void *val2 
= __CFArrayGetBucketAtIndex(array2
, idx
)->_item
; 
 305             if (NULL 
== cb1
->equal
) return false; 
 306             if (!INVOKE_CALLBACK2(cb1
->equal
, val1
, val2
)) return false; 
 312 static CFHashCode 
__CFArrayHash(CFTypeRef cf
) { 
 313     CFArrayRef array 
= (CFArrayRef
)cf
; 
 314     return __CFArrayGetCount(array
); 
 317 static CFStringRef 
__CFArrayCopyDescription(CFTypeRef cf
) { 
 318     CFArrayRef array 
= (CFArrayRef
)cf
; 
 319     CFMutableStringRef result
; 
 320     const CFArrayCallBacks 
*cb
; 
 321     CFAllocatorRef allocator
; 
 323     cnt 
= __CFArrayGetCount(array
); 
 324     allocator 
= CFGetAllocator(array
); 
 325     result 
= CFStringCreateMutable(allocator
, 0); 
 326     switch (__CFArrayGetType(array
)) { 
 327     case __kCFArrayImmutable
: 
 328         CFStringAppendFormat(result
, NULL
, CFSTR("<CFArray %p [%p]>{type = immutable, count = %u, values = (%s"), cf
, allocator
, cnt
, cnt 
? "\n" : ""); 
 330     case __kCFArrayDeque
: 
 331         CFStringAppendFormat(result
, NULL
, CFSTR("<CFArray %p [%p]>{type = mutable-small, count = %u, values = (%s"), cf
, allocator
, cnt
, cnt 
? "\n" : ""); 
 333     case __kCFArrayStorage
: 
 334         CFStringAppendFormat(result
, NULL
, CFSTR("<CFArray %p [%p]>{type = mutable-large, count = %u, values = (%s"), cf
, allocator
, cnt
, cnt 
? "\n" : ""); 
 337     cb 
= __CFArrayGetCallBacks(array
); 
 338     for (idx 
= 0; idx 
< cnt
; idx
++) { 
 339         CFStringRef desc 
= NULL
; 
 340         const void *val 
= __CFArrayGetBucketAtIndex(array
, idx
)->_item
; 
 341         if (NULL 
!= cb
->copyDescription
) { 
 342             desc 
= (CFStringRef
)INVOKE_CALLBACK1(cb
->copyDescription
, val
); 
 345             CFStringAppendFormat(result
, NULL
, CFSTR("\t%u : %@\n"), idx
, desc
); 
 348             CFStringAppendFormat(result
, NULL
, CFSTR("\t%u : <%p>\n"), idx
, val
); 
 351     CFStringAppend(result
, CFSTR(")}")); 
 356 static void __CFArrayDeallocate(CFTypeRef cf
) { 
 357     CFArrayRef array 
= (CFArrayRef
)cf
; 
 358     BEGIN_MUTATION(array
); 
 359     // Under GC, keep contents alive when we know we can, either standard callbacks or NULL 
 360     // if (__CFBitfieldGetValue(cf->info, 5, 4)) return; // bits only ever set under GC 
 361     CFAllocatorRef allocator 
= __CFGetAllocator(array
); 
 362     if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) { 
 363         // XXX_PCB keep array intact during finalization. 
 364         const CFArrayCallBacks 
*cb 
= __CFArrayGetCallBacks(array
); 
 365         if (cb
->retain 
== NULL 
&& cb
->release 
== NULL
) { 
 369         if (cb 
== &kCFTypeArrayCallBacks 
|| cb
->release 
== kCFTypeArrayCallBacks
.release
) { 
 371             for (CFIndex idx 
= 0; idx 
< __CFArrayGetCount(array
); idx
++) { 
 372                 const void *item 
= __CFArrayGetBucketAtIndex(array
, 0 + idx
)->_item
; 
 373                 kCFTypeArrayCallBacks
.release(kCFAllocatorSystemDefault
, item
); 
 379     __CFArrayReleaseValues(array
, CFRangeMake(0, __CFArrayGetCount(array
)), true); 
 383 static CFTypeID __kCFArrayTypeID 
= _kCFRuntimeNotATypeID
; 
 385 static const CFRuntimeClass __CFArrayClass 
= { 
 386     _kCFRuntimeScannedObject
, 
 394     __CFArrayCopyDescription
 
 397 __private_extern__ 
void __CFArrayInitialize(void) { 
 398     __kCFArrayTypeID 
= _CFRuntimeRegisterClass(&__CFArrayClass
); 
 401 CFTypeID 
CFArrayGetTypeID(void) { 
 402     return __kCFArrayTypeID
; 
 405 static CFArrayRef 
__CFArrayInit(CFAllocatorRef allocator
, UInt32 flags
, CFIndex capacity
, const CFArrayCallBacks 
*callBacks
) { 
 406     struct __CFArray 
*memory
; 
 408     __CFBitfieldSetValue(flags
, 31, 2, 0); 
 409     if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) { 
 410         if (!callBacks 
|| (callBacks
->retain 
== NULL 
&& callBacks
->release 
== NULL
)) { 
 411             __CFBitfieldSetValue(flags
, 4, 4, 1); // setWeak 
 414     if (__CFArrayCallBacksMatchNull(callBacks
)) { 
 415         __CFBitfieldSetValue(flags
, 3, 2, __kCFArrayHasNullCallBacks
); 
 416     } else if (__CFArrayCallBacksMatchCFType(callBacks
)) { 
 417         __CFBitfieldSetValue(flags
, 3, 2, __kCFArrayHasCFTypeCallBacks
); 
 419         __CFBitfieldSetValue(flags
, 3, 2, __kCFArrayHasCustomCallBacks
); 
 421     size 
= __CFArrayGetSizeOfType(flags
) - sizeof(CFRuntimeBase
); 
 422     switch (__CFBitfieldGetValue(flags
, 1, 0)) { 
 423     case __kCFArrayImmutable
: 
 424         size 
+= capacity 
* sizeof(struct __CFArrayBucket
); 
 426     case __kCFArrayDeque
: 
 427     case __kCFArrayStorage
: 
 430     memory 
= (struct __CFArray
*)_CFRuntimeCreateInstance(allocator
, __kCFArrayTypeID
, size
, NULL
); 
 431     if (NULL 
== memory
) { 
 434     __CFBitfieldSetValue(memory
->_base
._cfinfo
[CF_INFO_BITS
], 6, 0, flags
); 
 435     __CFArraySetCount((CFArrayRef
)memory
, 0); 
 436     switch (__CFBitfieldGetValue(flags
, 1, 0)) { 
 437     case __kCFArrayImmutable
: 
 438         if (isWeakMemory(memory
)) {  // if weak, don't scan 
 439             auto_zone_set_unscanned(auto_zone(), memory
); 
 441         if (__CFOASafe
) __CFSetLastAllocationEventName(memory
, "CFArray (immutable)"); 
 443     case __kCFArrayDeque
: 
 444     case __kCFArrayStorage
: 
 445         if (__CFOASafe
) __CFSetLastAllocationEventName(memory
, "CFArray (mutable-variable)"); 
 446         ((struct __CFArray 
*)memory
)->_mutations 
= 1; 
 447         ((struct __CFArray 
*)memory
)->_mutInProgress 
= 0; 
 448         ((struct __CFArray
*)memory
)->_store 
= NULL
; 
 451     if (__kCFArrayHasCustomCallBacks 
== __CFBitfieldGetValue(flags
, 3, 2)) { 
 452         CFArrayCallBacks 
*cb 
= (CFArrayCallBacks 
*)__CFArrayGetCallBacks((CFArrayRef
)memory
); 
 454         FAULT_CALLBACK((void **)&(cb
->retain
)); 
 455         FAULT_CALLBACK((void **)&(cb
->release
)); 
 456         FAULT_CALLBACK((void **)&(cb
->copyDescription
)); 
 457         FAULT_CALLBACK((void **)&(cb
->equal
)); 
 459     return (CFArrayRef
)memory
; 
 462 CFArrayRef 
CFArrayCreate(CFAllocatorRef allocator
, const void **values
, CFIndex numValues
, const CFArrayCallBacks 
*callBacks
) { 
 464     const CFArrayCallBacks 
*cb
; 
 465     struct __CFArrayBucket 
*buckets
; 
 466     CFAllocatorRef bucketsAllocator
; 
 469     CFAssert2(0 <= numValues
, __kCFLogAssertion
, "%s(): numValues (%d) cannot be less than zero", __PRETTY_FUNCTION__
, numValues
); 
 470     result 
= __CFArrayInit(allocator
, __kCFArrayImmutable
, numValues
, callBacks
); 
 471     cb 
= __CFArrayGetCallBacks(result
); 
 472     buckets 
= __CFArrayGetBucketsPtr(result
); 
 473     bucketsAllocator 
= isStrongMemory(result
) ? allocator 
: kCFAllocatorNull
; 
 474     bucketsBase 
= CF_IS_COLLECTABLE_ALLOCATOR(bucketsAllocator
) ? (void *)auto_zone_base_pointer(auto_zone(), buckets
) : NULL
; 
 475     if (NULL 
!= cb
->retain
) { 
 476         for (idx 
= 0; idx 
< numValues
; idx
++) { 
 477             __CFAssignWithWriteBarrier((void **)&buckets
->_item
, (void *)INVOKE_CALLBACK2(cb
->retain
, allocator
, *values
)); 
 483         for (idx 
= 0; idx 
< numValues
; idx
++) { 
 484             __CFAssignWithWriteBarrier((void **)&buckets
->_item
, (void *)*values
); 
 489     __CFArraySetCount(result
, numValues
); 
 493 CFMutableArrayRef 
CFArrayCreateMutable(CFAllocatorRef allocator
, CFIndex capacity
, const CFArrayCallBacks 
*callBacks
) { 
 494     CFAssert2(0 <= capacity
, __kCFLogAssertion
, "%s(): capacity (%d) cannot be less than zero", __PRETTY_FUNCTION__
, capacity
); 
 495     CFAssert2(capacity 
<= LONG_MAX 
/ sizeof(void *), __kCFLogAssertion
, "%s(): capacity (%d) is too large for this architecture", __PRETTY_FUNCTION__
, capacity
); 
 496     return (CFMutableArrayRef
)__CFArrayInit(allocator
, __kCFArrayDeque
, capacity
, callBacks
); 
 499 CFArrayRef 
CFArrayCreateCopy(CFAllocatorRef allocator
, CFArrayRef array
) { 
 501     const CFArrayCallBacks 
*cb
; 
 502     struct __CFArrayBucket 
*buckets
; 
 503     CFAllocatorRef bucketsAllocator
; 
 505     CFIndex numValues 
= CFArrayGetCount(array
); 
 507     if (CF_IS_OBJC(__kCFArrayTypeID
, array
)) { 
 508         cb 
= &kCFTypeArrayCallBacks
; 
 510         cb 
= __CFArrayGetCallBacks(array
); 
 512     result 
= __CFArrayInit(allocator
, __kCFArrayImmutable
, numValues
, cb
); 
 513     cb 
= __CFArrayGetCallBacks(result
); // GC: use the new array's callbacks so we don't leak. 
 514     buckets 
= __CFArrayGetBucketsPtr(result
); 
 515     bucketsAllocator 
= isStrongMemory(result
) ? allocator 
: kCFAllocatorNull
; 
 516         bucketsBase 
= CF_IS_COLLECTABLE_ALLOCATOR(bucketsAllocator
) ? (void *)auto_zone_base_pointer(auto_zone(), buckets
) : NULL
; 
 517     for (idx 
= 0; idx 
< numValues
; idx
++) { 
 518         const void *value 
= CFArrayGetValueAtIndex(array
, idx
); 
 519         if (NULL 
!= cb
->retain
) { 
 520             value 
= (void *)INVOKE_CALLBACK2(cb
->retain
, allocator
, value
); 
 522         __CFAssignWithWriteBarrier((void **)&buckets
->_item
, (void *)value
); 
 525     __CFArraySetCount(result
, numValues
); 
 529 CFMutableArrayRef 
CFArrayCreateMutableCopy(CFAllocatorRef allocator
, CFIndex capacity
, CFArrayRef array
) { 
 530     CFMutableArrayRef result
; 
 531     const CFArrayCallBacks 
*cb
; 
 532     CFIndex idx
, numValues 
= CFArrayGetCount(array
); 
 534     if (CF_IS_OBJC(__kCFArrayTypeID
, array
)) { 
 535         cb 
= &kCFTypeArrayCallBacks
; 
 538         cb 
= __CFArrayGetCallBacks(array
); 
 540     flags 
= __kCFArrayDeque
; 
 541     result 
= (CFMutableArrayRef
)__CFArrayInit(allocator
, flags
, capacity
, cb
); 
 542     if (0 == capacity
) _CFArraySetCapacity(result
, numValues
); 
 543     for (idx 
= 0; idx 
< numValues
; idx
++) { 
 544         const void *value 
= CFArrayGetValueAtIndex(array
, idx
); 
 545         CFArrayAppendValue(result
, value
); 
 550 CFIndex 
CFArrayGetCount(CFArrayRef array
) { 
 551     CF_OBJC_FUNCDISPATCH0(__kCFArrayTypeID
, CFIndex
, array
, "count"); 
 552     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 553     CHECK_FOR_MUTATION(array
); 
 554     return __CFArrayGetCount(array
); 
 558 CFIndex 
CFArrayGetCountOfValue(CFArrayRef array
, CFRange range
, const void *value
) { 
 559     const CFArrayCallBacks 
*cb
; 
 560     CFIndex idx
, count 
= 0; 
 561 // CF: this ignores range 
 562     CF_OBJC_FUNCDISPATCH1(__kCFArrayTypeID
, CFIndex
, array
, "_cfcountOccurrences:", value
); 
 563     __CFGenericValidateType(array
, __kCFArrayTypeID
);     
 564     __CFArrayValidateRange(array
, range
, __PRETTY_FUNCTION__
); 
 565     CHECK_FOR_MUTATION(array
); 
 566     cb 
= __CFArrayGetCallBacks(array
); 
 567     for (idx 
= 0; idx 
< range
.length
; idx
++) { 
 568         const void *item 
= __CFArrayGetBucketAtIndex(array
, range
.location 
+ idx
)->_item
; 
 569         if (value 
== item 
|| (cb
->equal 
&& INVOKE_CALLBACK2(cb
->equal
, value
, item
))) { 
 576 Boolean 
CFArrayContainsValue(CFArrayRef array
, CFRange range
, const void *value
) { 
 578     CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID
, char, array
, "containsObject:inRange:", value
, range
); 
 579     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 580     __CFArrayValidateRange(array
, range
, __PRETTY_FUNCTION__
); 
 581     CHECK_FOR_MUTATION(array
); 
 582     const CFArrayCallBacks 
*cb 
= __CFArrayGetCallBacks(array
); 
 583     for (idx 
= 0; idx 
< range
.length
; idx
++) { 
 584         const void *item 
= __CFArrayGetBucketAtIndex(array
, range
.location 
+ idx
)->_item
; 
 585         if (value 
== item 
|| (cb
->equal 
&& INVOKE_CALLBACK2(cb
->equal
, value
, item
))) { 
 592 const void *CFArrayGetValueAtIndex(CFArrayRef array
, CFIndex idx
) { 
 593     CF_OBJC_FUNCDISPATCH1(__kCFArrayTypeID
, void *, array
, "objectAtIndex:", idx
); 
 594     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 595     CFAssert2(0 <= idx 
&& idx 
< __CFArrayGetCount(array
), __kCFLogAssertion
, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__
, idx
); 
 596     CHECK_FOR_MUTATION(array
); 
 597     return __CFArrayGetBucketAtIndex(array
, idx
)->_item
; 
 600 // This is for use by NSCFArray; it avoids ObjC dispatch, and checks for out of bounds 
 601 const void *_CFArrayCheckAndGetValueAtIndex(CFArrayRef array
, CFIndex idx
) { 
 602     CHECK_FOR_MUTATION(array
); 
 603     if (0 <= idx 
&& idx 
< __CFArrayGetCount(array
)) return __CFArrayGetBucketAtIndex(array
, idx
)->_item
; 
 608 void CFArrayGetValues(CFArrayRef array
, CFRange range
, const void **values
) { 
 609     CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID
, void, array
, "getObjects:range:", values
, range
); 
 610     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 611     __CFArrayValidateRange(array
, range
, __PRETTY_FUNCTION__
); 
 612     CFAssert1(NULL 
!= values
, __kCFLogAssertion
, "%s(): pointer to values may not be NULL", __PRETTY_FUNCTION__
); 
 613     CHECK_FOR_MUTATION(array
); 
 614     if (0 < range
.length
) { 
 615         switch (__CFArrayGetType(array
)) { 
 616         case __kCFArrayImmutable
: 
 617         case __kCFArrayDeque
: 
 618             objc_memmove_collectable(values
, __CFArrayGetBucketsPtr(array
) + range
.location
, range
.length 
* sizeof(struct __CFArrayBucket
)); 
 620         case __kCFArrayStorage
: { 
 621             CFStorageRef store 
= (CFStorageRef
)array
->_store
; 
 622             CFStorageGetValues(store
, range
, values
); 
 630 CF_EXPORT 
unsigned long _CFArrayFastEnumeration(CFArrayRef array
, struct __objcFastEnumerationStateEquivalent 
*state
, void *stackbuffer
, unsigned long count
) { 
 631     CHECK_FOR_MUTATION(array
); 
 632     if (array
->_count 
== 0) return 0; 
 633     enum { ATSTART 
= 0, ATEND 
= 1 }; 
 634     switch (__CFArrayGetType(array
)) { 
 635     case __kCFArrayImmutable
: 
 636         if (state
->state 
== ATSTART
) { /* first time */ 
 637             static const unsigned long const_mu 
= 1; 
 638             state
->state 
= ATEND
; 
 639             state
->mutationsPtr 
= (unsigned long *)&const_mu
; 
 640             state
->itemsPtr 
= (unsigned long *)__CFArrayGetBucketsPtr(array
); 
 641             return array
->_count
; 
 644     case __kCFArrayDeque
: 
 645         if (state
->state 
== ATSTART
) { /* first time */ 
 646             state
->state 
= ATEND
; 
 647             state
->mutationsPtr 
= (unsigned long *)&array
->_mutations
; 
 648             state
->itemsPtr 
= (unsigned long *)__CFArrayGetBucketsPtr(array
); 
 649             return array
->_count
; 
 652     case __kCFArrayStorage
: 
 653         state
->mutationsPtr 
= (unsigned long *)&array
->_mutations
; 
 654         return _CFStorageFastEnumeration((CFStorageRef
)array
->_store
, state
, stackbuffer
, count
); 
 660 void CFArrayApplyFunction(CFArrayRef array
, CFRange range
, CFArrayApplierFunction applier
, void *context
) { 
 662     FAULT_CALLBACK((void **)&(applier
)); 
 663     CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID
, void, array
, "_cfapply:context:", applier
, context
); 
 664     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 665     __CFArrayValidateRange(array
, range
, __PRETTY_FUNCTION__
); 
 666     CFAssert1(NULL 
!= applier
, __kCFLogAssertion
, "%s(): pointer to applier function may not be NULL", __PRETTY_FUNCTION__
); 
 667     CHECK_FOR_MUTATION(array
); 
 668     for (idx 
= 0; idx 
< range
.length
; idx
++) { 
 669         const void *item 
= __CFArrayGetBucketAtIndex(array
, range
.location 
+ idx
)->_item
; 
 670         INVOKE_CALLBACK2(applier
, item
, context
); 
 674 CFIndex 
CFArrayGetFirstIndexOfValue(CFArrayRef array
, CFRange range
, const void *value
) { 
 675     const CFArrayCallBacks 
*cb
; 
 677     CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID
, CFIndex
, array
, "_cfindexOfObject:inRange:", value
, range
); 
 678     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 679     __CFArrayValidateRange(array
, range
, __PRETTY_FUNCTION__
); 
 680     CHECK_FOR_MUTATION(array
); 
 681     cb 
= __CFArrayGetCallBacks(array
); 
 682     for (idx 
= 0; idx 
< range
.length
; idx
++) { 
 683         const void *item 
= __CFArrayGetBucketAtIndex(array
, range
.location 
+ idx
)->_item
; 
 684         if (value 
== item 
|| (cb
->equal 
&& INVOKE_CALLBACK2(cb
->equal
, value
, item
))) 
 685             return idx 
+ range
.location
; 
 690 CFIndex 
CFArrayGetLastIndexOfValue(CFArrayRef array
, CFRange range
, const void *value
) { 
 691     const CFArrayCallBacks 
*cb
; 
 693     CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID
, CFIndex
, array
, "_cflastIndexOfObject:inRange:", value
, range
); 
 694     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 695     __CFArrayValidateRange(array
, range
, __PRETTY_FUNCTION__
); 
 696     CHECK_FOR_MUTATION(array
); 
 697     cb 
= __CFArrayGetCallBacks(array
); 
 698     for (idx 
= range
.length
; idx
--;) { 
 699         const void *item 
= __CFArrayGetBucketAtIndex(array
, range
.location 
+ idx
)->_item
; 
 700         if (value 
== item 
|| (cb
->equal 
&& INVOKE_CALLBACK2(cb
->equal
, value
, item
))) 
 701             return idx 
+ range
.location
; 
 706 void CFArrayAppendValue(CFMutableArrayRef array
, const void *value
) { 
 707     CF_OBJC_FUNCDISPATCH1(__kCFArrayTypeID
, void, array
, "addObject:", value
); 
 708     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 709     CFAssert1(__CFArrayGetType(array
) != __kCFArrayImmutable
, __kCFLogAssertion
, "%s(): array is immutable", __PRETTY_FUNCTION__
); 
 710     CHECK_FOR_MUTATION(array
); 
 711     _CFArrayReplaceValues(array
, CFRangeMake(__CFArrayGetCount(array
), 0), &value
, 1); 
 714 void CFArraySetValueAtIndex(CFMutableArrayRef array
, CFIndex idx
, const void *value
) { 
 715     CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID
, void, array
, "setObject:atIndex:", value
, idx
); 
 716     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 717     CFAssert1(__CFArrayGetType(array
) != __kCFArrayImmutable
, __kCFLogAssertion
, "%s(): array is immutable", __PRETTY_FUNCTION__
); 
 718     CFAssert2(0 <= idx 
&& idx 
<= __CFArrayGetCount(array
), __kCFLogAssertion
, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__
, idx
); 
 719     CHECK_FOR_MUTATION(array
); 
 720     if (idx 
== __CFArrayGetCount(array
)) { 
 721         _CFArrayReplaceValues(array
, CFRangeMake(idx
, 0), &value
, 1); 
 723         BEGIN_MUTATION(array
); 
 724         const void *old_value
; 
 725         const CFArrayCallBacks 
*cb 
= __CFArrayGetCallBacks(array
); 
 726         CFAllocatorRef allocator 
= __CFGetAllocator(array
); 
 727         struct __CFArrayBucket 
*bucket 
= __CFArrayGetBucketAtIndex(array
, idx
); 
 728         if (NULL 
!= cb
->retain 
&& !hasBeenFinalized(array
)) { 
 729             value 
= (void *)INVOKE_CALLBACK2(cb
->retain
, allocator
, value
); 
 731         old_value 
= bucket
->_item
; 
 732         __CFAssignWithWriteBarrier((void **)&bucket
->_item
, (void *)value
); // GC: handles deque/CFStorage cases. 
 733         if (NULL 
!= cb
->release 
&& !hasBeenFinalized(array
)) { 
 734             INVOKE_CALLBACK2(cb
->release
, allocator
, old_value
); 
 741 void CFArrayInsertValueAtIndex(CFMutableArrayRef array
, CFIndex idx
, const void *value
) { 
 742     CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID
, void, array
, "insertObject:atIndex:", value
, idx
); 
 743     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 744     CFAssert1(__CFArrayGetType(array
) != __kCFArrayImmutable
, __kCFLogAssertion
, "%s(): array is immutable", __PRETTY_FUNCTION__
); 
 745     CFAssert2(0 <= idx 
&& idx 
<= __CFArrayGetCount(array
), __kCFLogAssertion
, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__
, idx
); 
 746     CHECK_FOR_MUTATION(array
); 
 747     _CFArrayReplaceValues(array
, CFRangeMake(idx
, 0), &value
, 1); 
 750 void CFArrayExchangeValuesAtIndices(CFMutableArrayRef array
, CFIndex idx1
, CFIndex idx2
) { 
 752     struct __CFArrayBucket 
*bucket1
, *bucket2
; 
 753     CFAllocatorRef bucketsAllocator
; 
 754     CF_OBJC_FUNCDISPATCH2(__kCFArrayTypeID
, void, array
, "_cfexchange::", idx1
, idx2
); 
 755     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 756     CFAssert2(0 <= idx1 
&& idx1 
< __CFArrayGetCount(array
), __kCFLogAssertion
, "%s(): index #1 (%d) out of bounds", __PRETTY_FUNCTION__
, idx1
); 
 757     CFAssert2(0 <= idx2 
&& idx2 
< __CFArrayGetCount(array
), __kCFLogAssertion
, "%s(): index #2 (%d) out of bounds", __PRETTY_FUNCTION__
, idx2
); 
 758     CFAssert1(__CFArrayGetType(array
) != __kCFArrayImmutable
, __kCFLogAssertion
, "%s(): array is immutable", __PRETTY_FUNCTION__
); 
 759     CHECK_FOR_MUTATION(array
); 
 760     BEGIN_MUTATION(array
); 
 761     bucket1 
= __CFArrayGetBucketAtIndex(array
, idx1
); 
 762     bucket2 
= __CFArrayGetBucketAtIndex(array
, idx2
); 
 763     tmp 
= bucket1
->_item
; 
 764     bucketsAllocator 
= isStrongMemory(array
) ? __CFGetAllocator(array
) : kCFAllocatorNull
; 
 765     // XXX these aren't needed. 
 766     __CFAssignWithWriteBarrier((void **)&bucket1
->_item
, (void *)bucket2
->_item
); 
 767     __CFAssignWithWriteBarrier((void **)&bucket2
->_item
, (void *)tmp
); 
 772 void CFArrayRemoveValueAtIndex(CFMutableArrayRef array
, CFIndex idx
) { 
 773     CF_OBJC_FUNCDISPATCH1(__kCFArrayTypeID
, void, array
, "removeObjectAtIndex:", idx
); 
 774     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 775     CFAssert1(__CFArrayGetType(array
) != __kCFArrayImmutable
, __kCFLogAssertion
, "%s(): array is immutable", __PRETTY_FUNCTION__
); 
 776     CFAssert2(0 <= idx 
&& idx 
< __CFArrayGetCount(array
), __kCFLogAssertion
, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__
, idx
); 
 777     CHECK_FOR_MUTATION(array
); 
 778     _CFArrayReplaceValues(array
, CFRangeMake(idx
, 1), NULL
, 0); 
 781 void CFArrayRemoveAllValues(CFMutableArrayRef array
) { 
 782     CF_OBJC_FUNCDISPATCH0(__kCFArrayTypeID
, void, array
, "removeAllObjects"); 
 783     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 784     CFAssert1(__CFArrayGetType(array
) != __kCFArrayImmutable
, __kCFLogAssertion
, "%s(): array is immutable", __PRETTY_FUNCTION__
); 
 785     CHECK_FOR_MUTATION(array
); 
 786     BEGIN_MUTATION(array
); 
 787     __CFArrayReleaseValues(array
, CFRangeMake(0, __CFArrayGetCount(array
)), true); 
 788     __CFArraySetCount(array
, 0); 
 793 static void __CFArrayConvertDequeToStore(CFMutableArrayRef array
) { 
 794     struct __CFArrayDeque 
*deque 
= (struct __CFArrayDeque 
*)array
->_store
; 
 795     struct __CFArrayBucket 
*raw_buckets 
= (struct __CFArrayBucket 
*)((uint8_t *)deque 
+ sizeof(struct __CFArrayDeque
)); 
 797     CFIndex count 
= __CFArrayGetCount(array
); 
 798     CFAllocatorRef allocator 
= __CFGetAllocator(array
); 
 799     Boolean collectableMemory 
= CF_IS_COLLECTABLE_ALLOCATOR(allocator
); 
 800     if (collectableMemory
) auto_zone_retain(auto_zone(), deque
); 
 801     store 
= CFStorageCreate(allocator
, sizeof(const void *)); 
 802     if (__CFOASafe
) __CFSetLastAllocationEventName(store
, "CFArray (store-storage)"); 
 803     __CFAssignWithWriteBarrier((void **)&array
->_store
, (void *)store
); 
 804     CFMakeCollectable(store
);   // GC: now safe to unroot the store. 
 805     CFStorageInsertValues(store
, CFRangeMake(0, count
)); 
 806     CFStorageReplaceValues(store
, CFRangeMake(0, count
), raw_buckets 
+ deque
->_leftIdx
); 
 807     CFAllocatorDeallocate(__CFGetAllocator(array
), deque
); 
 808     __CFBitfieldSetValue(((CFRuntimeBase 
*)array
)->_cfinfo
[CF_INFO_BITS
], 1, 0, __kCFArrayStorage
); 
 811 static void __CFArrayConvertStoreToDeque(CFMutableArrayRef array
) { 
 812     CFStorageRef store 
= (CFStorageRef
)array
->_store
; 
 813     struct __CFArrayDeque 
*deque
; 
 814     struct __CFArrayBucket 
*raw_buckets
; 
 815     CFIndex count 
= CFStorageGetCount(store
);// storage, not array, has correct count at this point 
 816     // do not resize down to a completely tight deque 
 817     CFIndex capacity 
= __CFArrayDequeRoundUpCapacity(count 
+ 6); 
 818     CFIndex size 
= sizeof(struct __CFArrayDeque
) + capacity 
* sizeof(struct __CFArrayBucket
); 
 819     CFAllocatorRef allocator 
= __CFGetAllocator(array
); 
 820     Boolean collectableMemory 
= CF_IS_COLLECTABLE_ALLOCATOR(allocator
); 
 821     if (collectableMemory
) CFRetain(store
); // GC:  need to root the CFStorage 
 822     deque 
= (struct __CFArrayDeque 
*)CFAllocatorAllocate(allocator
, size
, isStrongMemory(array
) ? __kCFAllocatorGCScannedMemory 
: 0); 
 823     if (__CFOASafe
) __CFSetLastAllocationEventName(deque
, "CFArray (store-deque)"); 
 824     deque
->_leftIdx 
= (capacity 
- count
) / 2; 
 825     deque
->_capacity 
= capacity
; 
 827     __CFAssignWithWriteBarrier((void **)&array
->_store
, (void *)deque
); 
 828     if (collectableMemory
) auto_zone_release(auto_zone(), deque
); 
 829     raw_buckets 
= (struct __CFArrayBucket 
*)((uint8_t *)deque 
+ sizeof(struct __CFArrayDeque
)); 
 830     CFStorageGetValues(store
, CFRangeMake(0, count
), raw_buckets 
+ deque
->_leftIdx
); 
 832     __CFBitfieldSetValue(((CFRuntimeBase 
*)array
)->_cfinfo
[CF_INFO_BITS
], 1, 0, __kCFArrayDeque
); 
 835 // may move deque storage, as it may need to grow deque 
 836 static void __CFArrayRepositionDequeRegions(CFMutableArrayRef array
, CFRange range
, CFIndex newCount
) { 
 837     // newCount elements are going to replace the range, and the result will fit in the deque 
 838     struct __CFArrayDeque 
*deque 
= (struct __CFArrayDeque 
*)array
->_store
; 
 839     struct __CFArrayBucket 
*buckets
; 
 840     CFIndex cnt
, futureCnt
, numNewElems
; 
 841     CFIndex L
, A
, B
, C
, R
; 
 843     buckets 
= (struct __CFArrayBucket 
*)((uint8_t *)deque 
+ sizeof(struct __CFArrayDeque
)); 
 844     cnt 
= __CFArrayGetCount(array
); 
 845     futureCnt 
= cnt 
- range
.length 
+ newCount
; 
 847     L 
= deque
->_leftIdx
;                // length of region to left of deque 
 848     A 
= range
.location
;                 // length of region in deque to left of replaced range 
 849     B 
= range
.length
;                   // length of replaced range 
 850     C 
= cnt 
- B 
- A
;                    // length of region in deque to right of replaced range 
 851     R 
= deque
->_capacity 
- cnt 
- L
;     // length of region to right of deque 
 852     numNewElems 
= newCount 
- B
; 
 854     CFIndex wiggle 
= deque
->_capacity 
>> 17; 
 855     if (wiggle 
< 4) wiggle 
= 4; 
 856     if (deque
->_capacity 
< (uint32_t)futureCnt 
|| (cnt 
< futureCnt 
&& L 
+ R 
< wiggle
)) { 
 857         // must be inserting or space is tight, reallocate and re-center everything 
 858         CFIndex capacity 
= __CFArrayDequeRoundUpCapacity(futureCnt 
+ wiggle
); 
 859         CFIndex size 
= sizeof(struct __CFArrayDeque
) + capacity 
* sizeof(struct __CFArrayBucket
); 
 860         CFAllocatorRef allocator 
= __CFGetAllocator(array
); 
 861         struct __CFArrayDeque 
*newDeque 
= (struct __CFArrayDeque 
*)CFAllocatorAllocate(allocator
, size
, isStrongMemory(array
) ? __kCFAllocatorGCScannedMemory 
: 0); 
 862         if (__CFOASafe
) __CFSetLastAllocationEventName(newDeque
, "CFArray (store-deque)"); 
 863         struct __CFArrayBucket 
*newBuckets 
= (struct __CFArrayBucket 
*)((uint8_t *)newDeque 
+ sizeof(struct __CFArrayDeque
)); 
 865         CFIndex newL 
= (capacity 
- futureCnt
) / 2; 
 866         CFIndex oldC0 
= oldL 
+ A 
+ B
; 
 867         CFIndex newC0 
= newL 
+ A 
+ newCount
; 
 868         newDeque
->_leftIdx 
= newL
; 
 869         newDeque
->_capacity 
= capacity
; 
 871         if (0 < A
) objc_memmove_collectable(newBuckets 
+ newL
, buckets 
+ oldL
, A 
* sizeof(struct __CFArrayBucket
)); 
 872         if (0 < C
) objc_memmove_collectable(newBuckets 
+ newC0
, buckets 
+ oldC0
, C 
* sizeof(struct __CFArrayBucket
)); 
 873         if (deque
) _CFAllocatorDeallocateGC(allocator
, deque
); 
 874         __CFAssignWithWriteBarrier((void **)&array
->_store
, (void *)newDeque
); 
 875         if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) auto_zone_release(auto_zone(), newDeque
); 
 879     if ((numNewElems 
< 0 && C 
< A
) || (numNewElems 
<= R 
&& C 
< A
)) {    // move C 
 880         // deleting: C is smaller 
 881         // inserting: C is smaller and R has room 
 882         CFIndex oldC0 
= L 
+ A 
+ B
; 
 883         CFIndex newC0 
= L 
+ A 
+ newCount
; 
 884         if (0 < C
) objc_memmove_collectable(buckets 
+ newC0
, buckets 
+ oldC0
, C 
* sizeof(struct __CFArrayBucket
)); 
 885         // GrP GC: zero-out newly exposed space on the right, if any 
 886         if (oldC0 
> newC0
) memset(buckets 
+ newC0 
+ C
, 0, (oldC0 
- newC0
) * sizeof(struct __CFArrayBucket
)); 
 887     } else if ((numNewElems 
< 0) || (numNewElems 
<= L 
&& A 
<= C
)) {     // move A 
 888         // deleting: A is smaller or equal (covers remaining delete cases) 
 889         // inserting: A is smaller and L has room 
 891         CFIndex newL 
= L 
- numNewElems
; 
 892         deque
->_leftIdx 
= newL
; 
 893         if (0 < A
) objc_memmove_collectable(buckets 
+ newL
, buckets 
+ oldL
, A 
* sizeof(struct __CFArrayBucket
)); 
 894         // GrP GC: zero-out newly exposed space on the left, if any 
 895         if (newL 
> oldL
) memset(buckets 
+ oldL
, 0, (newL 
- oldL
) * sizeof(struct __CFArrayBucket
)); 
 897         // now, must be inserting, and either: 
 898         //    A<=C, but L doesn't have room (R might have, but don't care) 
 899         //    C<A, but R doesn't have room (L might have, but don't care) 
 900         // re-center everything 
 902         CFIndex newL 
= (L 
+ R 
- numNewElems
) / 2; 
 903         CFIndex oldBias 
= deque
->_bias
; 
 904         deque
->_bias 
= (newL 
< oldL
) ? -1 : 1; 
 906             newL 
= newL 
- newL 
/ 2; 
 907         } else if (0 < oldBias
) { 
 908             newL 
= newL 
+ newL 
/ 2; 
 910         CFIndex oldC0 
= oldL 
+ A 
+ B
; 
 911         CFIndex newC0 
= newL 
+ A 
+ newCount
; 
 912         deque
->_leftIdx 
= newL
; 
 914             if (0 < A
) objc_memmove_collectable(buckets 
+ newL
, buckets 
+ oldL
, A 
* sizeof(struct __CFArrayBucket
)); 
 915             if (0 < C
) objc_memmove_collectable(buckets 
+ newC0
, buckets 
+ oldC0
, C 
* sizeof(struct __CFArrayBucket
)); 
 916             // GrP GC: zero-out newly exposed space on the right, if any 
 917             if (oldC0 
> newC0
) memset(buckets 
+ newC0 
+ C
, 0, (oldC0 
- newC0
) * sizeof(struct __CFArrayBucket
)); 
 919             if (0 < C
) objc_memmove_collectable(buckets 
+ newC0
, buckets 
+ oldC0
, C 
* sizeof(struct __CFArrayBucket
)); 
 920             if (0 < A
) objc_memmove_collectable(buckets 
+ newL
, buckets 
+ oldL
, A 
* sizeof(struct __CFArrayBucket
)); 
 921             // GrP GC: zero-out newly exposed space on the left, if any 
 922             if (newL 
> oldL
) memset(buckets 
+ oldL
, 0, (newL 
- oldL
) * sizeof(struct __CFArrayBucket
)); 
 927 static void __CFArrayHandleOutOfMemory(CFTypeRef obj
, CFIndex numBytes
) { 
 928     CFStringRef msg 
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("Attempt to allocate %ld bytes for CFArray failed"), numBytes
); 
 930         CFLog(kCFLogLevelCritical
, CFSTR("%@"), msg
); 
 936 // This function is for Foundation's benefit; no one else should use it. 
 937 void _CFArraySetCapacity(CFMutableArrayRef array
, CFIndex cap
) { 
 938     if (CF_IS_OBJC(__kCFArrayTypeID
, array
)) return; 
 939     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 940     CFAssert1(__CFArrayGetType(array
) != __kCFArrayImmutable
, __kCFLogAssertion
, "%s(): array is immutable", __PRETTY_FUNCTION__
); 
 941     CFAssert3(__CFArrayGetCount(array
) <= cap
, __kCFLogAssertion
, "%s(): desired capacity (%d) is less than count (%d)", __PRETTY_FUNCTION__
, cap
, __CFArrayGetCount(array
)); 
 942     CHECK_FOR_MUTATION(array
); 
 943     BEGIN_MUTATION(array
); 
 944     // Currently, attempting to set the capacity of an array which is the CFStorage 
 945     // variant, or set the capacity larger than __CF_MAX_BUCKETS_PER_DEQUE, has no 
 946     // effect.  The primary purpose of this API is to help avoid a bunch of the 
 947     // resizes at the small capacities 4, 8, 16, etc. 
 948     if (__CFArrayGetType(array
) == __kCFArrayDeque
) { 
 949         struct __CFArrayDeque 
*deque 
= (struct __CFArrayDeque 
*)array
->_store
; 
 950         CFIndex capacity 
= __CFArrayDequeRoundUpCapacity(cap
); 
 951         CFIndex size 
= sizeof(struct __CFArrayDeque
) + capacity 
* sizeof(struct __CFArrayBucket
); 
 952         CFAllocatorRef allocator 
= __CFGetAllocator(array
); 
 953         Boolean collectableMemory 
= CF_IS_COLLECTABLE_ALLOCATOR(allocator
); 
 955             deque 
= (struct __CFArrayDeque 
*)CFAllocatorAllocate(allocator
, size
, isStrongMemory(array
) ? __kCFAllocatorGCScannedMemory 
: 0); 
 956             if (NULL 
== deque
) __CFArrayHandleOutOfMemory(array
, size
); 
 957             if (__CFOASafe
) __CFSetLastAllocationEventName(deque
, "CFArray (store-deque)"); 
 958             deque
->_leftIdx 
= capacity 
/ 2;  
 960             struct __CFArrayDeque 
*olddeque 
= deque
; 
 961             CFIndex oldcap 
= deque
->_capacity
; 
 962             deque 
= (struct __CFArrayDeque 
*)CFAllocatorAllocate(allocator
, size
, isStrongMemory(array
) ? __kCFAllocatorGCScannedMemory 
: 0); 
 963             if (NULL 
== deque
) __CFArrayHandleOutOfMemory(array
, size
); 
 964             objc_memmove_collectable(deque
, olddeque
, sizeof(struct __CFArrayDeque
) + oldcap 
* sizeof(struct __CFArrayBucket
)); 
 965             _CFAllocatorDeallocateGC(allocator
, olddeque
); 
 966             if (__CFOASafe
) __CFSetLastAllocationEventName(deque
, "CFArray (store-deque)"); 
 968         deque
->_capacity 
= capacity
; 
 970         __CFAssignWithWriteBarrier((void **)&array
->_store
, (void *)deque
); 
 971         if (collectableMemory
) auto_zone_release(auto_zone(), deque
); 
 977 void CFArrayReplaceValues(CFMutableArrayRef array
, CFRange range
, const void **newValues
, CFIndex newCount
) { 
 978     CF_OBJC_FUNCDISPATCH3(__kCFArrayTypeID
, void, array
, "replaceObjectsInRange:withObjects:count:", range
, (void **)newValues
, newCount
); 
 979     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
 980     __CFArrayValidateRange(array
, range
, __PRETTY_FUNCTION__
); 
 981     CFAssert1(__CFArrayGetType(array
) != __kCFArrayImmutable
, __kCFLogAssertion
, "%s(): array is immutable", __PRETTY_FUNCTION__
); 
 982     CFAssert2(0 <= newCount
, __kCFLogAssertion
, "%s(): newCount (%d) cannot be less than zero", __PRETTY_FUNCTION__
, newCount
); 
 983     CHECK_FOR_MUTATION(array
); 
 984     return _CFArrayReplaceValues(array
, range
, newValues
, newCount
); 
 987 // This function does no ObjC dispatch or argument checking; 
 988 // It should only be called from places where that dispatch and check has already been done, or NSCFArray 
 989 void _CFArrayReplaceValues(CFMutableArrayRef array
, CFRange range
, const void **newValues
, CFIndex newCount
) { 
 990     CHECK_FOR_MUTATION(array
); 
 991     BEGIN_MUTATION(array
); 
 992     const CFArrayCallBacks 
*cb
; 
 993     CFAllocatorRef allocator
; 
 994     CFIndex idx
, cnt
, futureCnt
; 
 995     const void **newv
, *buffer
[256]; 
 996     cnt 
= __CFArrayGetCount(array
); 
 997     futureCnt 
= cnt 
- range
.length 
+ newCount
; 
 998     CFAssert1(newCount 
<= futureCnt
, __kCFLogAssertion
, "%s(): internal error 1", __PRETTY_FUNCTION__
); 
 999     cb 
= __CFArrayGetCallBacks(array
); 
1000     allocator 
= __CFGetAllocator(array
); 
1002     /* Retain new values if needed, possibly allocating a temporary buffer for them */ 
1003     if (NULL 
!= cb
->retain 
&& !hasBeenFinalized(array
)) { 
1004         newv 
= (newCount 
<= 256) ? (const void **)buffer 
: (const void **)CFAllocatorAllocate(allocator
, newCount 
* sizeof(void *), 0); // GC OK 
1005         if (newv 
!= buffer 
&& __CFOASafe
) __CFSetLastAllocationEventName(newv
, "CFArray (temp)"); 
1006         for (idx 
= 0; idx 
< newCount
; idx
++) { 
1007             newv
[idx
] = (void *)INVOKE_CALLBACK2(cb
->retain
, allocator
, (void *)newValues
[idx
]); 
1012     array
->_mutations
++; 
1014     /* Now, there are three regions of interest, each of which may be empty: 
1015      *   A: the region from index 0 to one less than the range.location 
1016      *   B: the region of the range 
1017      *   C: the region from range.location + range.length to the end 
1018      * Note that index 0 is not necessarily at the lowest-address edge 
1019      * of the available storage. The values in region B need to get 
1020      * released, and the values in regions A and C (depending) need 
1021      * to get shifted if the number of new values is different from 
1022      * the length of the range being replaced. 
1024     if (0 < range
.length
) { 
1025         __CFArrayReleaseValues(array
, range
, false); 
1027     // region B elements are now "dead" 
1028     if (__kCFArrayStorage 
== __CFArrayGetType(array
)) { 
1029         CFStorageRef store 
= (CFStorageRef
)array
->_store
; 
1030         // reposition regions A and C for new region B elements in gap 
1031         if (range
.length 
< newCount
) { 
1032             CFStorageInsertValues(store
, CFRangeMake(range
.location 
+ range
.length
, newCount 
- range
.length
)); 
1033         } else if (newCount 
< range
.length
) { 
1034             CFStorageDeleteValues(store
, CFRangeMake(range
.location 
+ newCount
, range
.length 
- newCount
)); 
1036         if (futureCnt 
<= __CF_MAX_BUCKETS_PER_DEQUE 
/ 2) { 
1037             __CFArrayConvertStoreToDeque(array
); 
1039     } else if (NULL 
== array
->_store
) { 
1040         if (__CF_MAX_BUCKETS_PER_DEQUE 
<= futureCnt
) { 
1041             CFStorageRef store 
= CFStorageCreate(allocator
, sizeof(const void *)); 
1042             if (! isStrongMemory(array
)) _CFStorageSetWeak(store
); 
1043             if (__CFOASafe
) __CFSetLastAllocationEventName(store
, "CFArray (store-storage)"); 
1044             __CFAssignWithWriteBarrier((void **)&array
->_store
, (void *)store
); 
1045             CFMakeCollectable(store
); 
1046             CFStorageInsertValues(store
, CFRangeMake(0, newCount
)); 
1047             __CFBitfieldSetValue(((CFRuntimeBase 
*)array
)->_cfinfo
[CF_INFO_BITS
], 1, 0, __kCFArrayStorage
); 
1048         } else if (0 <= futureCnt
) { 
1049             struct __CFArrayDeque 
*deque
; 
1050             CFIndex capacity 
= __CFArrayDequeRoundUpCapacity(futureCnt
); 
1051             CFIndex size 
= sizeof(struct __CFArrayDeque
) + capacity 
* sizeof(struct __CFArrayBucket
); 
1052             deque 
= (struct __CFArrayDeque 
*)CFAllocatorAllocate(allocator
, size
, isStrongMemory(array
) ? __kCFAllocatorGCScannedMemory 
: 0); 
1053             if (__CFOASafe
) __CFSetLastAllocationEventName(deque
, "CFArray (store-deque)"); 
1054             deque
->_leftIdx 
= (capacity 
- newCount
) / 2; 
1055             deque
->_capacity 
= capacity
; 
1057             __CFAssignWithWriteBarrier((void **)&array
->_store
, (void *)deque
); 
1058             if (CF_IS_COLLECTABLE_ALLOCATOR(allocator
)) auto_zone_release(auto_zone(), deque
); // GC: now safe to unroot the array body. 
1061         // reposition regions A and C for new region B elements in gap 
1062         if (__CF_MAX_BUCKETS_PER_DEQUE 
<= futureCnt
) { 
1064             __CFArrayConvertDequeToStore(array
); 
1065             store 
= (CFStorageRef
)array
->_store
; 
1066             if (range
.length 
< newCount
) { 
1067                 CFStorageInsertValues(store
, CFRangeMake(range
.location 
+ range
.length
, newCount 
- range
.length
)); 
1068             } else if (newCount 
< range
.length
) { // this won't happen, but is here for completeness 
1069                 CFStorageDeleteValues(store
, CFRangeMake(range
.location 
+ newCount
, range
.length 
- newCount
)); 
1071         } else if (range
.length 
!= newCount
) { 
1072             __CFArrayRepositionDequeRegions(array
, range
, newCount
); 
1075     // copy in new region B elements 
1077         if (__kCFArrayStorage 
== __CFArrayGetType(array
)) { 
1078             CFStorageRef store 
= (CFStorageRef
)array
->_store
; 
1079             CFStorageReplaceValues(store
, CFRangeMake(range
.location
, newCount
), newv
); 
1081             struct __CFArrayDeque 
*deque 
= (struct __CFArrayDeque 
*)array
->_store
; 
1082             struct __CFArrayBucket 
*raw_buckets 
= (struct __CFArrayBucket 
*)((uint8_t *)deque 
+ sizeof(struct __CFArrayDeque
)); 
1083             objc_memmove_collectable(raw_buckets 
+ deque
->_leftIdx 
+ range
.location
, newv
, newCount 
* sizeof(struct __CFArrayBucket
)); 
1086     __CFArraySetCount(array
, futureCnt
); 
1087     if (newv 
!= buffer 
&& newv 
!= newValues
) CFAllocatorDeallocate(allocator
, newv
); 
1088     END_MUTATION(array
); 
1091 struct _acompareContext 
{ 
1092     CFComparatorFunction func
; 
1096 static CFComparisonResult 
__CFArrayCompareValues(const void *v1
, const void *v2
, struct _acompareContext 
*context
) { 
1097     const void **val1 
= (const void **)v1
; 
1098     const void **val2 
= (const void **)v2
; 
1099     return (CFComparisonResult
)(INVOKE_CALLBACK3(context
->func
, *val1
, *val2
, context
->context
)); 
1102 void CFArraySortValues(CFMutableArrayRef array
, CFRange range
, CFComparatorFunction comparator
, void *context
) { 
1103     FAULT_CALLBACK((void **)&(comparator
)); 
1104     CF_OBJC_FUNCDISPATCH3(__kCFArrayTypeID
, void, array
, "sortUsingFunction:context:range:", comparator
, context
, range
); 
1105     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
1106     __CFArrayValidateRange(array
, range
, __PRETTY_FUNCTION__
); 
1107     CFAssert1(__CFArrayGetType(array
) != __kCFArrayImmutable
, __kCFLogAssertion
, "%s(): array is immutable", __PRETTY_FUNCTION__
); 
1108     CFAssert1(NULL 
!= comparator
, __kCFLogAssertion
, "%s(): pointer to comparator function may not be NULL", __PRETTY_FUNCTION__
); 
1109     CHECK_FOR_MUTATION(array
); 
1110     BEGIN_MUTATION(array
); 
1111     array
->_mutations
++; 
1113     if (1 < range
.length
) { 
1114         struct _acompareContext ctx
; 
1115         struct __CFArrayBucket 
*bucket
; 
1116         ctx
.func 
= comparator
; 
1117         ctx
.context 
= context
; 
1118         switch (__CFArrayGetType(array
)) { 
1119         case __kCFArrayDeque
: 
1120             bucket 
= __CFArrayGetBucketsPtr(array
) + range
.location
; 
1121             CFQSortArray(bucket
, range
.length
, sizeof(void *), (CFComparatorFunction
)__CFArrayCompareValues
, &ctx
); 
1123         case __kCFArrayStorage
: { 
1124             CFStorageRef store 
= (CFStorageRef
)array
->_store
; 
1125             const void **values
, *buffer
[256]; 
1126             values 
= (range
.length 
<= 256) ? (const void **)buffer 
: (const void **)CFAllocatorAllocate(kCFAllocatorSystemDefault
, range
.length 
* sizeof(void *), 0); // GC OK 
1127             if (values 
!= buffer 
&& __CFOASafe
) __CFSetLastAllocationEventName(values
, "CFArray (temp)"); 
1128             CFStorageGetValues(store
, range
, values
); 
1129             CFQSortArray(values
, range
.length
, sizeof(void *), (CFComparatorFunction
)__CFArrayCompareValues
, &ctx
); 
1130             CFStorageReplaceValues(store
, range
, values
); 
1131             if (values 
!= buffer
) CFAllocatorDeallocate(kCFAllocatorSystemDefault
, values
);  // GC OK 
1136     END_MUTATION(array
); 
1139 CFIndex 
CFArrayBSearchValues(CFArrayRef array
, CFRange range
, const void *value
, CFComparatorFunction comparator
, void *context
) { 
1140     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
1141     __CFArrayValidateRange(array
, range
, __PRETTY_FUNCTION__
); 
1142     CFAssert1(NULL 
!= comparator
, __kCFLogAssertion
, "%s(): pointer to comparator function may not be NULL", __PRETTY_FUNCTION__
); 
1143     bool isObjC 
= CF_IS_OBJC(__kCFArrayTypeID
, array
); 
1144     FAULT_CALLBACK((void **)&(comparator
)); 
1145     if (!isObjC
) CHECK_FOR_MUTATION(array
); 
1147     if (range
.length 
<= 0) return range
.location
; 
1148     if (isObjC 
|| __kCFArrayStorage 
== __CFArrayGetType(array
)) { 
1151         item 
= CFArrayGetValueAtIndex(array
, range
.location 
+ range
.length 
- 1); 
1152         if ((CFComparisonResult
)(INVOKE_CALLBACK3(comparator
, item
, value
, context
)) < 0) { 
1153             return range
.location 
+ range
.length
; 
1155         item 
= CFArrayGetValueAtIndex(array
, range
.location
); 
1156         if ((CFComparisonResult
)(INVOKE_CALLBACK3(comparator
, value
, item
, context
)) < 0) { 
1157             return range
.location
; 
1159         lg 
= flsl(range
.length
) - 1;    // lg2(range.length) 
1160         item 
= CFArrayGetValueAtIndex(array
, range
.location 
+ -1 + (1 << lg
)); 
1161         idx 
= range
.location 
+ ((CFComparisonResult
)(INVOKE_CALLBACK3(comparator
, item
, value
, context
)) < 0) ? range
.length 
- (1 << lg
) : -1; 
1163             item 
= CFArrayGetValueAtIndex(array
, range
.location 
+ idx 
+ (1 << lg
)); 
1164             if ((CFComparisonResult
)(INVOKE_CALLBACK3(comparator
, item
, value
, context
)) < 0) { 
1170         struct _acompareContext ctx
; 
1171         ctx
.func 
= comparator
; 
1172         ctx
.context 
= context
; 
1173         idx 
= CFBSearch(&value
, sizeof(void *), __CFArrayGetBucketsPtr(array
) + range
.location
, range
.length
, (CFComparatorFunction
)__CFArrayCompareValues
, &ctx
); 
1175     return idx 
+ range
.location
; 
1178 void CFArrayAppendArray(CFMutableArrayRef array
, CFArrayRef otherArray
, CFRange otherRange
) { 
1180     __CFGenericValidateType(array
, __kCFArrayTypeID
); 
1181     __CFGenericValidateType(otherArray
, __kCFArrayTypeID
); 
1182     CFAssert1(__CFArrayGetType(array
) != __kCFArrayImmutable
, __kCFLogAssertion
, "%s(): array is immutable", __PRETTY_FUNCTION__
); 
1183     __CFArrayValidateRange(otherArray
, otherRange
, __PRETTY_FUNCTION__
); 
1184     CHECK_FOR_MUTATION(array
); 
1185     for (idx 
= otherRange
.location
; idx 
< otherRange
.location 
+ otherRange
.length
; idx
++) { 
1186         CFArrayAppendValue(array
, CFArrayGetValueAtIndex(otherArray
, idx
)); 
1190 // ----====---- ----====---- ----====---- ----====---- 
1192 __private_extern__ Boolean 
__CFArray6130(CFMutableArrayRef array
, CFIndex 
*p
, void **list
) { 
1193     if (CF_IS_OBJC(__kCFArrayTypeID
, array
)) return false; 
1194     CHECK_FOR_MUTATION(array
); 
1195     if (__kCFArrayStorage 
== __CFArrayGetType(array
)) { 
1196         CFStorageRef store 
= (CFStorageRef
)array
->_store
; 
1197         CFRange range 
= {0, 0}; 
1199         for (CFIndex idx 
= 0; idx 
< __CFArrayGetCount(array
); idx
++) { 
1200             if (range
.location 
+ range
.length 
- 1 < idx
) { 
1201                 bytes 
= CFStorageGetValueAtIndex(store
, idx
, &range
); 
1203             ((void **)bytes
)[idx 
- range
.location
] = list
[p
[idx
]]; 
1205     } else if (kCFUseCollectableAllocator
) {        // Deque 
1206         struct __CFArrayDeque 
*deque 
= (struct __CFArrayDeque 
*)array
->_store
; 
1207         struct __CFArrayBucket 
*raw_buckets 
= (struct __CFArrayBucket 
*)((uint8_t *)deque 
+ sizeof(struct __CFArrayDeque
)) + deque
->_leftIdx
; 
1208         for (CFIndex idx 
= 0; idx 
< __CFArrayGetCount(array
); idx
++) { 
1209             struct __CFArrayBucket 
*dest 
= raw_buckets 
+ idx
; 
1210             objc_memmove_collectable(dest
, list 
+ p
[idx
], sizeof(struct __CFArrayBucket
)); 
1213         struct __CFArrayDeque 
*deque 
= (struct __CFArrayDeque 
*)array
->_store
; 
1214         struct __CFArrayBucket 
*raw_buckets 
= (struct __CFArrayBucket 
*)((uint8_t *)deque 
+ sizeof(struct __CFArrayDeque
)) + deque
->_leftIdx
; 
1215         for (CFIndex idx 
= 0; idx 
< __CFArrayGetCount(array
); idx
++) { 
1216             raw_buckets
[idx
]._item 
= list
[p
[idx
]];