/*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* @APPLE_LICENSE_HEADER_END@
*/
/* CFBitVector.c
- Copyright 1998-2002, Apple, Inc. All rights reserved.
+ Copyright (c) 1998-2009, Apple Inc. All rights reserved.
Responsibility: Christopher Kane
*/
typedef uint8_t __CFBitVectorBucket;
enum {
- __CF_BITS_PER_BYTE = 8
+ __CF_BITS_PER_BYTE = 8,
+ __CF_BITS_PER_BYTE_MASK = 0x07
};
enum {
- __CF_BITS_PER_BUCKET = (__CF_BITS_PER_BYTE * sizeof(__CFBitVectorBucket))
+ __CF_BITS_PER_BUCKET = (__CF_BITS_PER_BYTE * sizeof(__CFBitVectorBucket)),
+ __CF_BITS_PER_BUCKET_MASK = 0x07 // __CF_BITS_PER_BYTE_MASK * lg2(sizeof(__CFBitVectorBucket))
};
CF_INLINE CFIndex __CFBitVectorRoundUpCapacity(CFIndex capacity) {
+ if (0 == capacity) capacity = 1;
return ((capacity + 63) / 64) * 64;
}
CF_INLINE CFIndex __CFBitVectorNumBucketsForCapacity(CFIndex capacity) {
- return (capacity + __CF_BITS_PER_BUCKET - 1) / __CF_BITS_PER_BUCKET;
+ return capacity / __CF_BITS_PER_BUCKET + ((capacity & __CF_BITS_PER_BUCKET_MASK) ? 1 : 0);
}
struct __CFBitVector {
}
enum {
- kCFBitVectorImmutable = 0x0, /* unchangable and fixed capacity; default */
+ kCFBitVectorImmutable = 0x0, /* unchangable and fixed capacity; default */
kCFBitVectorMutable = 0x1, /* changeable and variable capacity */
- kCFBitVectorFixedMutable = 0x3 /* changeable and fixed capacity */
};
static void __CFBitVectorDeallocate(CFTypeRef cf) {
CFMutableBitVectorRef bv = (CFMutableBitVectorRef)cf;
CFAllocatorRef allocator = CFGetAllocator(bv);
- if (__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable) {
- _CFAllocatorDeallocateGC(allocator, bv->_buckets);
- }
+ if (bv->_buckets) _CFAllocatorDeallocateGC(allocator, bv->_buckets);
}
static CFTypeID __kCFBitVectorTypeID = _kCFRuntimeNotATypeID;
CFMutableBitVectorRef memory;
CFIndex size;
CFAssert2(0 <= capacity, __kCFLogAssertion, "%s(): capacity (%d) cannot be less than zero", __PRETTY_FUNCTION__, capacity);
- CFAssert3(kCFBitVectorFixedMutable != __CFBitVectorMutableVarietyFromFlags(flags) || numBits <= capacity, __kCFLogAssertion, "%s(): for fixed mutable bit vectors, capacity (%d) must be greater than or equal to number of initial elements (%d)", __PRETTY_FUNCTION__, capacity, numBits);
CFAssert2(0 <= numBits, __kCFLogAssertion, "%s(): numValues (%d) cannot be less than zero", __PRETTY_FUNCTION__, numBits);
size = sizeof(struct __CFBitVector) - sizeof(CFRuntimeBase);
- if (__CFBitVectorMutableVarietyFromFlags(flags) != kCFBitVectorMutable)
- size += sizeof(__CFBitVectorBucket) * __CFBitVectorNumBucketsForCapacity(capacity);
memory = (CFMutableBitVectorRef)_CFRuntimeCreateInstance(allocator, __kCFBitVectorTypeID, size, NULL);
if (NULL == memory) {
return NULL;
}
- switch (__CFBitVectorMutableVarietyFromFlags(flags)) {
- case kCFBitVectorMutable:
- __CFBitVectorSetCapacity(memory, __CFBitVectorRoundUpCapacity(1));
- __CFBitVectorSetNumBuckets(memory, __CFBitVectorNumBucketsForCapacity(__CFBitVectorRoundUpCapacity(1)));
- CF_WRITE_BARRIER_BASE_ASSIGN(allocator, memory, memory->_buckets, _CFAllocatorAllocateGC(allocator, __CFBitVectorNumBuckets(memory) * sizeof(__CFBitVectorBucket), 0));
- if (__CFOASafe) __CFSetLastAllocationEventName(memory->_buckets, "CFBitVector (store)");
- if (NULL == memory->_buckets) {
- CFRelease(memory);
- return NULL;
- }
- break;
- case kCFBitVectorFixedMutable:
- case kCFBitVectorImmutable:
- /* Don't round up capacity */
- __CFBitVectorSetCapacity(memory, capacity);
- __CFBitVectorSetNumBuckets(memory, __CFBitVectorNumBucketsForCapacity(capacity));
- memory->_buckets = (__CFBitVectorBucket *)((int8_t *)memory + sizeof(struct __CFBitVector));
- break;
+ __CFBitVectorSetCapacity(memory, __CFBitVectorRoundUpCapacity(numBits));
+ __CFBitVectorSetNumBuckets(memory, __CFBitVectorNumBucketsForCapacity(__CFBitVectorRoundUpCapacity(numBits)));
+ __CFAssignWithWriteBarrier((void **)&memory->_buckets, _CFAllocatorAllocateGC(allocator, __CFBitVectorNumBuckets(memory) * sizeof(__CFBitVectorBucket), 0));
+ if (__CFOASafe) __CFSetLastAllocationEventName(memory->_buckets, "CFBitVector (store)");
+ if (NULL == memory->_buckets) {
+ CFRelease(memory);
+ return NULL;
}
+ memset(memory->_buckets, 0, __CFBitVectorNumBuckets(memory) * sizeof(__CFBitVectorBucket));
__CFBitVectorSetNumBucketsUsed(memory, numBits / __CF_BITS_PER_BUCKET + 1);
__CFBitVectorSetCount(memory, numBits);
if (bytes) {
/* This move is possible because bits are numbered from 0 on the left */
- memmove(memory->_buckets, bytes, (numBits + __CF_BITS_PER_BYTE - 1) / __CF_BITS_PER_BYTE);
+ memmove(memory->_buckets, bytes, numBits / __CF_BITS_PER_BYTE + (numBits & __CF_BITS_PER_BYTE_MASK ? 1 : 0));
}
__CFBitVectorSetMutableVariety(memory, __CFBitVectorMutableVarietyFromFlags(flags));
return memory;
}
CFMutableBitVectorRef CFBitVectorCreateMutable(CFAllocatorRef allocator, CFIndex capacity) {
- return __CFBitVectorInit(allocator, (0 == capacity) ? kCFBitVectorMutable : kCFBitVectorFixedMutable, capacity, NULL, 0);
+ return __CFBitVectorInit(allocator, kCFBitVectorMutable, capacity, NULL, 0);
}
CFBitVectorRef CFBitVectorCreateCopy(CFAllocatorRef allocator, CFBitVectorRef bv) {
CFMutableBitVectorRef CFBitVectorCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFBitVectorRef bv) {
__CFGenericValidateType(bv, __kCFBitVectorTypeID);
- return __CFBitVectorInit(allocator, (0 == capacity) ? kCFBitVectorMutable : kCFBitVectorFixedMutable, capacity, (const uint8_t *)bv->_buckets, __CFBitVectorCount(bv));
+ return __CFBitVectorInit(allocator, kCFBitVectorMutable, capacity, (const uint8_t *)bv->_buckets, __CFBitVectorCount(bv));
}
CFIndex CFBitVectorGetCount(CFBitVectorRef bv) {
CFAllocatorRef allocator = CFGetAllocator(bv);
__CFBitVectorSetCapacity(bv, capacity);
__CFBitVectorSetNumBuckets(bv, __CFBitVectorNumBucketsForCapacity(capacity));
- CF_WRITE_BARRIER_BASE_ASSIGN(allocator, bv, bv->_buckets, CFAllocatorReallocate(allocator, bv->_buckets, __CFBitVectorNumBuckets(bv) * sizeof(__CFBitVectorBucket), 0));
+ __CFAssignWithWriteBarrier((void **)&bv->_buckets, CFAllocatorReallocate(allocator, bv->_buckets, __CFBitVectorNumBuckets(bv) * sizeof(__CFBitVectorBucket), 0));
if (__CFOASafe) __CFSetLastAllocationEventName(bv->_buckets, "CFBitVector (store)");
if (NULL == bv->_buckets) HALT;
}
void CFBitVectorSetCount(CFMutableBitVectorRef bv, CFIndex count) {
CFIndex cnt;
- CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable || __CFBitVectorMutableVariety(bv) == kCFBitVectorFixedMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
+ CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
cnt = __CFBitVectorCount(bv);
switch (__CFBitVectorMutableVariety(bv)) {
case kCFBitVectorMutable:
__CFBitVectorGrow(bv, count - cnt);
}
break;
- case kCFBitVectorFixedMutable:
- CFAssert1(count <= __CFBitVectorCapacity(bv), __kCFLogAssertion, "%s(): fixed-capacity bit vector is full", __PRETTY_FUNCTION__);
- break;
}
if (cnt < count) {
CFRange range = CFRangeMake(cnt, count - cnt);
void CFBitVectorFlipBitAtIndex(CFMutableBitVectorRef bv, CFIndex idx) {
__CFGenericValidateType(bv, __kCFBitVectorTypeID);
CFAssert2(0 <= idx && idx < __CFBitVectorCount(bv), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx);
- CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable || __CFBitVectorMutableVariety(bv) == kCFBitVectorFixedMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
+ CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
__CFFlipBitVectorBit(bv->_buckets, idx);
}
void CFBitVectorFlipBits(CFMutableBitVectorRef bv, CFRange range) {
__CFGenericValidateType(bv, __kCFBitVectorTypeID);
__CFBitVectorValidateRange(bv, range, __PRETTY_FUNCTION__);
- CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable || __CFBitVectorMutableVariety(bv) == kCFBitVectorFixedMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
+ CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
if (0 == range.length) return;
__CFBitVectorInternalMap(bv, range, __CFBitVectorFlipBits, NULL);
}
void CFBitVectorSetBitAtIndex(CFMutableBitVectorRef bv, CFIndex idx, CFBit value) {
__CFGenericValidateType(bv, __kCFBitVectorTypeID);
CFAssert2(0 <= idx && idx < __CFBitVectorCount(bv), __kCFLogAssertion, "%s(): index (%d) out of bounds", __PRETTY_FUNCTION__, idx);
- CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable || __CFBitVectorMutableVariety(bv) == kCFBitVectorFixedMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
+ CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
__CFSetBitVectorBit(bv->_buckets, idx, value);
}
void CFBitVectorSetBits(CFMutableBitVectorRef bv, CFRange range, CFBit value) {
__CFGenericValidateType(bv, __kCFBitVectorTypeID);
__CFBitVectorValidateRange(bv, range, __PRETTY_FUNCTION__);
- CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable || __CFBitVectorMutableVariety(bv) == kCFBitVectorFixedMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
+ CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable , __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
if (0 == range.length) return;
if (value) {
__CFBitVectorInternalMap(bv, range, __CFBitVectorOneBits, NULL);
void CFBitVectorSetAllBits(CFMutableBitVectorRef bv, CFBit value) {
CFIndex nBuckets, leftover;
__CFGenericValidateType(bv, __kCFBitVectorTypeID);
- CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable || __CFBitVectorMutableVariety(bv) == kCFBitVectorFixedMutable, __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
+ CFAssert1(__CFBitVectorMutableVariety(bv) == kCFBitVectorMutable , __kCFLogAssertion, "%s(): bit vector is immutable", __PRETTY_FUNCTION__);
nBuckets = __CFBitVectorCount(bv) / __CF_BITS_PER_BUCKET;
leftover = __CFBitVectorCount(bv) - nBuckets * __CF_BITS_PER_BUCKET;
if (0 < leftover) {