Permalink
Browse files

Completed AQBitfield tests.

  • Loading branch information...
1 parent 805a1de commit 6dc3604af2c285875ab7e5514220a16952d4e3ab Jim Dovey committed Jun 22, 2011
Showing with 121 additions and 21 deletions.
  1. +0 −2 AQAppStateMachine/AQBitfield.h
  2. +54 −17 AQAppStateMachine/AQBitfield.m
  3. +67 −2 AQAppStateMachineTests/AQBitfieldTests.m
@@ -25,8 +25,6 @@ typedef CFBit AQBit;
- (AQBitfield *) bitfieldFromRange: (NSRange) range; // throws NSRangeException
-@property (nonatomic, readonly) NSData * bits;
-
- (NSUInteger) firstIndexOfBit: (AQBit) bit;
- (NSUInteger) lastIndexOfBit: (AQBit) bit;
@@ -104,12 +104,6 @@ - (AQBitfield *) bitfieldFromRange: (NSRange) range
return ( result );
}
-- (NSData *) bits
-{
- // TODO: Implement
- return ( nil );
-}
-
- (NSUInteger) firstIndexOfBit: (AQBit) bit
{
if ( bit )
@@ -121,7 +115,7 @@ - (NSUInteger) firstIndexOfBit: (AQBit) bit
{
[_storage enumerateRangesUsingBlock: ^(NSRange range, BOOL *stop) {
if ( range.location == 0 )
- result = NSMaxRange(range)+1;
+ result = NSMaxRange(range);
*stop = YES;
}];
}
@@ -147,8 +141,36 @@ - (NSUInteger) lastIndexOfBit: (AQBit) bit
if ( bit )
return ( [_storage lastIndex] );
- // TODO: Search for negative space
- return ( 0 );
+ __block NSUInteger result = NSNotFound;
+
+ if ( [_storage respondsToSelector: @selector(enumerateRangesUsingBlock:)] )
+ {
+ [_storage enumerateRangesWithOptions: NSEnumerationReverse usingBlock: ^(NSRange range, BOOL *stop) {
+ if ( NSMaxRange(range) < NSNotFound-1 )
+ {
+ result = NSNotFound-1;
+ }
+ else if ( range.location > 0 )
+ {
+ result = range.location-1;
+ }
+
+ *stop = YES;
+ }];
+ }
+ else
+ {
+ __block NSUInteger lastLowest = NSNotFound-1;
+ [_storage enumerateIndexesWithOptions: NSEnumerationReverse usingBlock: ^(NSUInteger idx, BOOL *stop) {
+ if ( idx < lastLowest-1 )
+ {
+ result = lastLowest-1;
+ *stop = YES;
+ }
+ }];
+ }
+
+ return ( result );
}
- (void) flipBitAtIndex: (NSUInteger) index
@@ -185,7 +207,7 @@ - (void) setBitsInRange: (NSRange) range usingBit: (AQBit) bit
- (void) setAllBits: (AQBit) bit
{
- [_storage addIndexesInRange: NSMakeRange(0, NSUIntegerMax)];
+ [_storage addIndexesInRange: NSMakeRange(0, NSNotFound)];
}
- (NSMutableIndexSet *) _zeroBasedIndexSetForIndexesInRange: (NSRange) range
@@ -259,13 +281,14 @@ - (BOOL) bitsInRange: (NSRange) range maskedWith: (AQBitfield *) mask equalToBit
if ( range.length == 0 )
return ( NO );
- NSMutableIndexSet * tmp = [self _zeroBasedIndexSetForIndexesInRange: range];
- NSMutableIndexSet * test = [bitfield->_storage mutableCopy];
+ AQBitfield * tmp1 = [self bitfieldFromRange: range];
+ [tmp1 maskWithBits: mask];
- [tmp removeIndexes: mask->_storage];
- [test removeIndexes: mask->_storage];
+ AQBitfield * tmp2 = [bitfield copy];
+ [tmp2 maskWithBits: mask];
+ [tmp2->_storage removeIndexesInRange: NSMakeRange(range.length, NSUIntegerMax-range.length)];
- return ( [tmp isEqualToIndexSet: test] );
+ return ( [tmp1 isEqual: tmp2] );
}
- (void) shiftBitsLeftBy: (NSUInteger) bits
@@ -294,16 +317,30 @@ - (void) maskWithBits: (AQBitfield *) mask
negativeRangeLocation = NSMaxRange(range);
}];
- if ( negativeRangeLocation < [_storage lastIndex] )
+ if ( negativeRangeLocation <= [_storage lastIndex] )
{
[_storage removeIndexesInRange: NSMakeRange(negativeRangeLocation, NSUIntegerMax-negativeRangeLocation)];
}
}
else
{
+ __block NSRange negativeRange = NSMakeRange(0, 0);
[mask->_storage enumerateIndexesInRange: range options: 0 usingBlock: ^(NSUInteger idx, BOOL *stop) {
- // TODO: Implement
+ if ( idx != 0 && NSMaxRange(negativeRange) < idx-1 )
+ {
+ // expand negative range to fill the area below current index and remove all indices from local storage
+ negativeRange.length = idx-negativeRange.location;
+ [_storage removeIndexesInRange: negativeRange];
+ }
+
+ negativeRange.location = idx+1;
}];
+
+ if ( negativeRange.location <= [_storage lastIndex] )
+ {
+ negativeRange.length = [_storage lastIndex] - negativeRange.location;
+ [_storage removeIndexesInRange: negativeRange];
+ }
}
}
@@ -106,6 +106,50 @@ - (void) testCopy
STAssertEqualObjects(bitfield, theCopy, @"Expected %@ to be equal to its copy %@", bitfield, theCopy);
}
+- (void) testFirstIndexOfBit
+{
+ AQBitfield * bitfield = [AQBitfield new];
+ [bitfield setBitsInRange: NSMakeRange(0, 20) usingBit: 1];
+
+ STAssertTrue([bitfield firstIndexOfBit: 1] == 0, @"Expected first index of bit 1 in %@ to be 0, instead got %lu", bitfield, (unsigned long)[bitfield firstIndexOfBit: 1]);
+ STAssertTrue([bitfield firstIndexOfBit: 0] == 20, @"Expected first index of bit 0 in %@ to be 20, instead got %lu", bitfield, (unsigned long)[bitfield firstIndexOfBit: 0]);
+}
+
+- (void) testLastIndexOfBit
+{
+ AQBitfield * bitfield = [AQBitfield new];
+ [bitfield setAllBits: 1];
+ [bitfield setBitsInRange: NSMakeRange(0, 20) usingBit: 0];
+
+ STAssertTrue([bitfield lastIndexOfBit: 1] == NSNotFound-1, @"Expected last index of bit 1 in %@ to be %lu, instead got %lu", bitfield, NSNotFound-1, (unsigned long)[bitfield lastIndexOfBit: 1]);
+ STAssertTrue([bitfield lastIndexOfBit: 0] == 19, @"Expected last index of bit 0 in %@ to be 19, instead got %lu", bitfield, (unsigned long)[bitfield lastIndexOfBit: 0]);
+}
+
+- (void) testFlipBitAtIndex
+{
+ AQBitfield * bitfield = [AQBitfield new];
+ NSRange rng = NSMakeRange(0, 20);
+ [bitfield setBitsInRange: rng usingBit: 1];
+ [bitfield flipBitAtIndex: 10];
+
+ STAssertTrue([bitfield countOfBit: 1 inRange: rng] == 19, @"Expected bitfield with 20 set bits and 1 toggled to have 19 set bits in range 0-20, instead got %lu", (unsigned long)[bitfield countOfBit: 1 inRange: rng]);
+ STAssertTrue([bitfield bitAtIndex: 10] == 0, @"Expected bitfield with 20 set bits and 1 toggled at index 10 to have a 0 bit at index 10");
+}
+
+- (void) testFlipBits
+{
+ AQBitfield * bitfield1 = [AQBitfield new];
+ NSRange rng = NSMakeRange(0, 20);
+ [bitfield1 setBitsInRange: rng usingBit: 1];
+ [bitfield1 setBit: 0 atIndex: 10];
+
+ AQBitfield * bitfield2 = [AQBitfield new];
+ [bitfield2 setBit: 1 atIndex: 10];
+
+ [bitfield1 flipBitsInRange: rng];
+ STAssertEqualObjects(bitfield1, bitfield2, @"Expected bitfield %@ with bits in range 0..20 flipped to equal bitfield %@", bitfield1, bitfield2);
+}
+
- (void) testBitShifts
{
AQBitfield * bitfield1 = [AQBitfield new];
@@ -159,6 +203,26 @@ - (void) testBitsInRangeAgainstBitfield
STAssertFalse([bitfield bitsInRange: rng equalToBitfield: test], @"Expected bits in range %@ of %@ to NOT match %@", NSStringFromRange(rng), bitfield, test);
}
+- (void) testMaskWithBits
+{
+ AQBitfield * bitfield = [AQBitfield new];
+ [bitfield setBitsInRange: NSMakeRange(0, 20) usingBit: 1];
+ [bitfield setBit: 0 atIndex: 15];
+ // 11111111111111101111
+
+ AQBitfield * mask = [AQBitfield new];
+ [mask setBitsInRange: NSMakeRange(5, 5) usingBit: 1];
+ [mask setBit: 1 atIndex: 15];
+ // 00000111110000010000
+
+ AQBitfield * expected = [AQBitfield new];
+ [expected setBitsInRange: NSMakeRange(5, 5) usingBit: 1];
+
+ AQBitfield * result = [bitfield copy];
+ [result maskWithBits: mask];
+ STAssertEqualObjects(result, expected, @"Expected %@ masked with %@ to equal %@, but instead got %@", bitfield, mask, expected, result);
+}
+
- (void) testMaskedBitsInRangeAgainstInteger
{
AQBitfield * bitfield = [AQBitfield new];
@@ -188,8 +252,9 @@ - (void) testMaskedBitsInRangeAgainstBitfield
rng.length = 100-20;
AQBitfield * mask = [AQBitfield new];
- [mask setBitsInRange: NSMakeRange(0, 7) usingBit: 1];
- [mask setBitsInRange: NSMakeRange(8, 7) usingBit: 1];
+ [mask setBitsInRange: NSMakeRange(0, 16) usingBit: 1];
+ [mask setBit: 0 atIndex: 7];
+ [mask setBit: 0 atIndex: 15];
[mask setBit: 1 atIndex: 80];
STAssertTrue([bitfield bitsInRange: rng maskedWith: mask equalToBitfield: test], @"Expected bits in range %@ of %@ masked with %@ to match %@", NSStringFromRange(rng), bitfield, mask, test);

0 comments on commit 6dc3604

Please sign in to comment.