Skip to content

Commit

Permalink
Almost finished porting AQBitfield to use NSMutableIndexSet for stora…
Browse files Browse the repository at this point in the history
…ge. Already looks much cleaner.
  • Loading branch information
Jim Dovey committed Jun 17, 2011
1 parent f6a66d7 commit 7b9d3bf
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 92 deletions.
6 changes: 1 addition & 5 deletions AQAppStateMachine/AQBitfield.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,10 @@ typedef CFBit AQBit;

@interface AQBitfield : NSObject <NSCopying, NSMutableCopying, NSCoding>

+ (AQBitfield *) bitfieldWithSize: (NSUInteger) numberOfBits;

- (id) initWithSize: (NSUInteger) numberOfBits;

- (NSUInteger) hash;
- (BOOL) isEqual: (id) object;

@property (nonatomic, assign) NSUInteger count; // number of significant bits
@property (nonatomic, readonly) NSUInteger count; // number of significant bits

- (NSUInteger) countOfBit: (AQBit) bit inRange: (NSRange) range;

Expand Down
136 changes: 49 additions & 87 deletions AQAppStateMachine/AQBitfield.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,76 +8,39 @@

#import "AQBitfield.h"

#define NSMakeRangeFromCF(cfr) NSMakeRange( cfr.location == kCFNotFound ? NSNotFound : cfr.location, cfr.length )
#define CFMakeRangeFromNS(nsr) CFRangeMake( nsr.location == NSNotFound ? kCFNotFound : nsr.location, nsr.length )

@implementation AQBitfield
{
CFMutableBitVectorRef _vector;
}

+ (AQBitfield *) bitfieldWithSize: (NSUInteger) numberOfBits
{
return ( [[self alloc] initWithSize: numberOfBits] );
NSMutableIndexSet * _storage;
}

- (id) initWithSize: (NSUInteger) numberOfBits
- (id) init
{
self = [super init];
if ( self == nil )
return ( nil );

_vector = CFBitVectorCreateMutable(kCFAllocatorDefault, numberOfBits);
if ( _vector == NULL )
self = nil; // release via ARC
_storage = [NSMutableIndexSet new];

return ( self );
}

- (id) initWithCoder: (NSCoder *) aDecoder
{
self = [super init];

NSData * bits = [aDecoder decodeObjectForKey: @"bitVectorData"];
CFBitVectorRef immutable = CFBitVectorCreate(kCFAllocatorDefault, (const UInt8 *)[bits bytes], [bits length] * sizeof(uint8_t));
if ( immutable == NULL )
{
self = nil;
return ( nil );
}

_vector = CFBitVectorCreateMutableCopy(kCFAllocatorDefault, CFBitVectorGetCount(immutable), immutable);

CFRelease(immutable);
_storage = [[aDecoder decodeObjectForKey: @"bitVectorData"] mutableCopy];

return ( self );
}

- (void) dealloc
{
// yay ARC! No -release this or -release that! Except I'm using malloc, so:
if ( _vector != NULL )
CFRelease( _vector );

// however: I don't need to call [super dealloc] under ARC -- WIN!
}

- (void) encodeWithCoder: (NSCoder *) aCoder
{
CFRange rng = CFRangeMake(0, CFBitVectorGetCount(_vector));
NSUInteger len = rng.length / sizeof(UInt8);

UInt8 * bytes = malloc(rng.length / sizeof(UInt8));
CFBitVectorGetBits(_vector, rng, bytes);

NSData * data = [NSData dataWithBytesNoCopy: bytes length: len]; // transfers ownership of bytes
[aCoder encodeObject: data forKey: @"bitVectorData"];
[aCoder encodeObject: _storage forKey: @"bitVectorData"];
}

- (id) copyWithZone:(NSZone *)zone
{
AQBitfield * bitfield = [[[self class] alloc] init];
bitfield->_vector = CFBitVectorCreateMutableCopy(kCFAllocatorDefault, CFBitVectorGetCount(_vector), _vector);
[bitfield->_storage addIndexes: _storage];
return ( bitfield );
}

Expand All @@ -88,19 +51,12 @@ - (id) mutableCopyWithZone:(NSZone *)zone

- (NSString *) description
{
NSMutableString * desc = [objc_retainedObject(CFCopyDescription(_vector)) mutableCopy];
NSRange rng = [desc rangeOfString: @">"];
if ( rng.location == NSNotFound )
return ( [desc copy] );

[desc replaceCharactersInRange: NSMakeRange(0, rng.location+1)
withString: [NSString stringWithFormat: @"<AQBitfield %p>", self]];
return ( [desc copy] );
return ( [NSString stringWithFormat: @"<AQBitfield %p>{_storage = %@}", self, _storage] );
}

- (NSUInteger) hash
{
return ( (NSUInteger)CFHash(_vector) );
return ( [_storage hash] );
}

- (BOOL) isEqual: (id) object
Expand All @@ -109,95 +65,101 @@ - (BOOL) isEqual: (id) object
return ( NO );

AQBitfield * other = (AQBitfield *)object;
if ( self.count != other.count )
return ( NO );

return ( (BOOL)CFEqual(_vector, other->_vector) );
return ( [_storage isEqualToIndexSet: other->_storage] );
}

- (NSUInteger) count
{
return ( (NSUInteger)CFBitVectorGetCount(_vector) );
}

- (void) setCount: (NSUInteger) count
{
CFBitVectorSetCount(_vector, count);
return ( [_storage lastIndex] + 1 );
}

- (NSUInteger) countOfBit: (AQBit) bit inRange: (NSRange) range
{
return ( (NSUInteger)CFBitVectorGetCountOfBit(_vector, CFMakeRangeFromNS(range), (CFBit)bit) );
return ( [_storage countOfIndexesInRange: range] );
}

- (BOOL) containsBit: (AQBit) bit inRange: (NSRange) range
{
return ( (BOOL)CFBitVectorContainsBit(_vector, CFMakeRangeFromNS(range), (CFBit)bit) );
if ( bit )
return ( [_storage containsIndexesInRange: range] );

return ( [_storage countOfIndexesInRange: range] < range.length );
}

- (AQBit) bitAtIndex: (NSUInteger) index
{
return ( (AQBit)CFBitVectorGetBitAtIndex(_vector, (CFIndex)index) );
if ( [_storage containsIndex: index] )
return ( 1 );

return ( 0 );
}

- (AQBitfield *) bitfieldFromRange: (NSRange) range
{
NSParameterAssert(range.length != 0);
UInt8 * bytes = malloc(range.length / sizeof(UInt8));
CFBitVectorGetBits(_vector, CFMakeRangeFromNS(range), bytes);

AQBitfield * result = [[AQBitfield alloc] init];
CFBitVectorRef immutable = CFBitVectorCreate(kCFAllocatorDefault, bytes, (CFIndex)range.length);
result->_vector = CFBitVectorCreateMutableCopy(kCFAllocatorDefault, (CFIndex)range.length, immutable);
CFRelease(immutable);

[result->_storage addIndexes: [_storage indexesInRange: range options: 0 passingTest:^BOOL(NSUInteger idx, BOOL *stop) { return YES; }]];
return ( result );
}

- (NSData *) bits
{
if ( CFBitVectorGetCount(_vector) == 0 )
return ( [NSData data] );

NSUInteger byteSize = CFBitVectorGetCount(_vector) / sizeof(UInt8);
UInt8 * bytes = malloc(byteSize);
CFBitVectorGetBits(_vector, CFRangeMake(0, CFBitVectorGetCount(_vector)), bytes);
return ( [NSData dataWithBytesNoCopy: bytes length: byteSize] );
// TODO: Implement
return ( nil );
}

- (NSUInteger) firstIndexOfBit: (AQBit) bit
{
return ( (NSUInteger)CFBitVectorGetFirstIndexOfBit(_vector, CFRangeMake(0, CFBitVectorGetCount(_vector)), (CFBit)bit) );
if ( bit )
return ( [_storage firstIndex] );

// TODO: Search for negative space
return ( 0 );
}

- (NSUInteger) lastIndexOfBit: (AQBit) bit
{
return ( (NSUInteger)CFBitVectorGetLastIndexOfBit(_vector, CFRangeMake(0, CFBitVectorGetCount(_vector)), (AQBit)bit) );
if ( bit )
return ( [_storage lastIndex] );

// TODO: Search for negative space
return ( 0 );
}

- (void) flipBitAtIndex: (NSUInteger) index
{
CFBitVectorFlipBitAtIndex(_vector, (CFIndex)index);
if ( [_storage containsIndex: index] )
[_storage removeIndex: index];
else
[_storage addIndex: index];
}

- (void) flipBitsInRange: (NSRange) range
{
CFBitVectorFlipBits(_vector, CFMakeRangeFromNS(range));
for ( NSUInteger i = range.location; i < NSMaxRange(range); i++ )
{
[self flipBitAtIndex: i];
}
}

- (void) setBit: (AQBit) bit atIndex: (NSUInteger) index
{
CFBitVectorSetBitAtIndex(_vector, (CFIndex)index, (CFBit)bit);
if ( bit )
[_storage addIndex: index];
else
[_storage removeIndex: index];
}

- (void) setBitsInRange: (NSRange) range usingBit: (AQBit) bit
{
CFBitVectorSetBits(_vector, CFMakeRangeFromNS(range), (CFBit)bit);
if ( bit )
[_storage addIndexesInRange: range];
else
[_storage removeIndexesInRange: range];
}

- (void) setAllBits: (AQBit) bit
{
CFBitVectorSetBits(_vector, CFRangeMake(0, CFBitVectorGetCount(_vector)), (CFBit)bit);
[_storage addIndexesInRange: NSMakeRange(0, NSUIntegerMax)];
}

- (BOOL) bitsInRange: (NSRange) range matchBits: (NSUInteger) bits
Expand Down

0 comments on commit 7b9d3bf

Please sign in to comment.