Skip to content

Commit

Permalink
Some more helper routines and tests for the state machine and underly…
Browse files Browse the repository at this point in the history
…ing bitfield.
  • Loading branch information
Jim Dovey committed Jul 18, 2011
1 parent 0f07514 commit 6c04370
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 9 deletions.
12 changes: 11 additions & 1 deletion AQAppStateMachine/AQAppStateMachine.h
Expand Up @@ -46,6 +46,11 @@
*/
+ (AQAppStateMachine *) appStateMachine;

// core value change API
- (void) setBit: (AQBit) aBit atIndex: (NSUInteger) index ofStateBitsInRange: (NSRange) range;
- (void) setScalar32Value: (UInt32) value forStateBitsInRange: (NSRange) range;
- (void) setScalar64Value: (UInt64) value forStateBitsInRange: (NSRange) range;

// core notification API— everything else funnels through these functions
- (void) notifyForChangesToStateBitAtIndex: (NSUInteger) index
usingBlock: (void (^)(void)) block;
Expand Down Expand Up @@ -87,7 +92,7 @@

@end

/*!
/**
This category defines an interface whereby API clients can interact with the state machine using
atomic-sized enumerated value ranges keyed with specific names, rather than knowing the internals
of the (potentially quite large) bitfield layout.
Expand All @@ -103,6 +108,11 @@
// generic named bit-range creator -- the others all funnel through here
- (void) addStateMachineValuesUsingBitfieldOfLength: (NSUInteger) length withName: (NSString *) name;

// setting values -- simple version
- (void) setValue: (UInt64) value forEnumerationWithName: (NSString *) name;
- (void) setBitAtIndex: (NSUInteger) index ofEnumerationWithName: (NSString *) name;
- (void) clearBitAtIndex: (NSUInteger) index ofEnumerationWithName: (NSString *) name;

// add notifications for named enumerations
- (void) notifyChangesToStateMachineValuesWithName: (NSString *) name
usingBlock: (void (^)(void)) block;
Expand Down
42 changes: 42 additions & 0 deletions AQAppStateMachine/AQAppStateMachine.m
Expand Up @@ -135,6 +135,21 @@ - (void) notifyForChangesToStateBitsInRange: (NSRange) range usingBlock: (void (
#endif
}

- (void) setBit: (AQBit) aBit atIndex: (NSUInteger) index ofStateBitsInRange: (NSRange) range
{
[_stateBits setBit: aBit atIndex: range.location + index];
}

- (void) setScalar32Value: (UInt32) value forStateBitsInRange: (NSRange) range
{
[_stateBits setBitsInRange: range from32BitValue: value];
}

- (void) setScalar64Value: (UInt64) value forStateBitsInRange: (NSRange) range
{
[_stateBits setBitsInRange: range from64BitValue: value];
}

- (void) notifyForChangesToStateBitsInRange: (NSRange) range
maskedWithInteger: (NSUInteger) mask
usingBlock: (void (^)(void)) block
Expand Down Expand Up @@ -283,6 +298,33 @@ - (void) addStateMachineValuesUsingBitfieldOfLength: (NSUInteger) length withNam
});
}

- (void) setValue: (UInt64) value forEnumerationWithName: (NSString *) name
{
NSRange rng = [self underlyingBitfieldRangeForName: name];
if ( rng.location == NSNotFound )
return;

[self setScalar64Value: value forStateBitsInRange: rng];
}

- (void) setBitAtIndex: (NSUInteger) index ofEnumerationWithName: (NSString *) name
{
NSRange rng = [self underlyingBitfieldRangeForName: name];
if ( rng.location == NSNotFound )
return;

[self setBit: 1 atIndex: index ofStateBitsInRange: rng];
}

- (void) clearBitAtIndex: (NSUInteger) index ofEnumerationWithName: (NSString *) name
{
NSRange rng = [self underlyingBitfieldRangeForName: name];
if ( rng.location == NSNotFound )
return;

[self setBit: 0 atIndex: index ofStateBitsInRange: rng];
}

- (void) notifyChangesToStateMachineValuesWithName: (NSString *) name
usingBlock: (void (^)(void)) block
{
Expand Down
18 changes: 17 additions & 1 deletion AQAppStateMachine/AQBitfield.h
Expand Up @@ -198,11 +198,27 @@ typedef CFBit AQBit;
- (void) setBitsFrom32BitValue: (UInt32) value;

/**
Set the bits in the least-significant four words to those in a 64-bit quantity.
Set the bits in the least-significant eight words to those in a 64-bit quantity.
@param value The value whose bits to copy.
*/
- (void) setBitsFrom64BitValue: (UInt64) value;

/**
Set the bits in the given range to those in a 32-bit quantity.
@param value The value whose bits to copy.
@param range The range of bits to modify.
@exception NSInvalidArgumentException Thrown if the supplied range is greater than 32 bits in length.
*/
- (void) setBitsInRange: (NSRange) range from32BitValue: (UInt32) value;

/**
Set the bits in the given range to those in a 64-bit quantity.
@param value The value whose bits to copy.
@param range The range of bits to modify.
@exception NSInvalidArgumentException Thrown if the supplied range is greater than 64 bits in length.
*/
- (void) setBitsInRange: (NSRange) range from64BitValue: (UInt64) value;

/**
Copy all 1 bits from another bitfield.
@param bitfield The bitfield with which to merge the receiver.
Expand Down
28 changes: 28 additions & 0 deletions AQAppStateMachine/AQBitfield.m
Expand Up @@ -338,6 +338,34 @@ - (void) setBitsFrom64BitValue: (UInt64) value
}
}

- (void) setBitsInRange: (NSRange) range from32BitValue: (UInt32) value
{
if ( range.length > 32 )
[NSException raise: NSInvalidArgumentException format: @"Range supplied to -%@ must have a length of 32 or less (received range %@)", NSStringFromClass([self class]), NSStringFromRange(range)];

for ( NSUInteger i = 0; i < range.length; i++, value >>= 1 )
{
if ( (value & 1) == 1 )
[_storage addIndex: range.location + i];
else
[_storage removeIndex: range.location + i];
}
}

- (void) setBitsInRange: (NSRange) range from64BitValue: (UInt64) value
{
if ( range.length > 64 )
[NSException raise: NSInvalidArgumentException format: @"Range supplied to -%@ must have a length of 64 or less (received range %@)", NSStringFromClass([self class]), NSStringFromRange(range)];

for ( NSUInteger i = 0; i < range.length; i++, value >>= 1 )
{
if ( (value & 1) == 1 )
[_storage addIndex: range.location + i];
else
[_storage removeIndex: range.location + i];
}
}

- (void) unionWithBitfield: (AQBitfield *) bitfield
{
[_storage addIndexes: bitfield->_storage];
Expand Down
6 changes: 3 additions & 3 deletions AQAppStateMachine/SortedDictionary/Public/SortedDictionary.m
Expand Up @@ -17,18 +17,18 @@ @implementation SortedDictionary
// terminated argument list
- (id) initWithObject: (id) firstObject andArglist: (va_list) arglist {
if (self = [self init]) {
id key, value;
id __unsafe_unretained key, value;

if ((value = firstObject)) {
if ((key = va_arg(arglist, id)) != nil) {
if ((key = va_arg(arglist, __unsafe_unretained id)) != nil) {
do {
if (!key || !value) {
@throw [NSException exceptionWithName: NSInvalidArgumentException
reason: @"nil key or value" userInfo: nil];
}

[tree setObject: value forKey: key];
} while ((value = va_arg(arglist, id)) && (key = va_arg(arglist, id)));
} while ((value = va_arg(arglist, __unsafe_unretained id)) && (key = va_arg(arglist, __unsafe_unretained id)));
}
}
}
Expand Down
22 changes: 19 additions & 3 deletions AQAppStateMachineTests/AQAppStateMachineCoreTests.m
Expand Up @@ -54,16 +54,28 @@
};

@implementation AQAppStateMachineCoreTests
{
AQAppStateMachine * stateMachine;
}

- (void) testNamedRanges
- (void) setUp
{
// temporary version just for the tests
AQAppStateMachine * stateMachine = [AQAppStateMachine new];
stateMachine = [AQAppStateMachine new];

// add the named ranges
[stateMachine addStateMachineValuesFromZeroTo: kSampleOneCount withName: @"Sample One"];
[stateMachine addStateMachineValuesFromZeroTo: kSampleTwoCount withName: @"Sample Two"];

}

- (void) tearDown
{
// ARC code-- no -release, just nilify it
stateMachine = nil;
}

- (void) testNamedRanges
{
// the state machine will round up to byte-size to allocate ranges, like so:
NSUInteger sampleOneBitCount = (kSampleOneCount + 7) & ~7;
NSUInteger sampleTwoBitCount = (kSampleTwoCount + 7) & ~7;
Expand All @@ -72,4 +84,8 @@ - (void) testNamedRanges
STAssertTrue(NSEqualRanges(NSMakeRange(sampleOneBitCount, sampleTwoBitCount), [stateMachine underlyingBitfieldRangeForName: @"Sample Two"]), @"The underlying range is unexpectedly %@", NSStringFromRange([stateMachine underlyingBitfieldRangeForName: @"Sample Two"]));
}

- (void) testChangesToSingleBit
{
}

@end
2 changes: 1 addition & 1 deletion AQAppStateMachineTests/AQAppStateMachineTests-Info.plist
Expand Up @@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.${PRODUCT_NAME:rfc1034identifier}</string>
<string>net.alanquatermain.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
Expand Down
50 changes: 50 additions & 0 deletions AQAppStateMachineTests/AQBitfieldTests.m
Expand Up @@ -112,6 +112,56 @@ - (void) testSetBitsFrom64BitScalar
STAssertTrue([bitfield countOfBit: 1 inRange: test6] == 3, @"Expected %@ to have 3 bits set in range %@, but got %lu", bitfield, NSStringFromRange(test3), (unsigned long)[bitfield countOfBit: 1 inRange: test6]);
}

- (void) setSetBitsInRangeFrom32BitScalar
{
AQBitfield * bitfield = [AQBitfield new];

NSRange setRange = NSMakeRange(10, 32);
[bitfield setBitsInRange: setRange from32BitValue: 0xFF00FFFF];

NSRange test1 = NSMakeRange(setRange.location, 16); // should be 16 bits set
NSRange test2 = NSMakeRange(setRange.location + 16, 8); // should be 0 bits set
NSRange test3 = NSMakeRange(setRange.location + 24, 8); // should be 8 bits set

STAssertTrue([bitfield countOfBit: 1 inRange: test1] == 16, @"Expected %@ to have 16 bits set in range %@, but got %lu", bitfield, NSStringFromRange(test1), (unsigned long)[bitfield countOfBit: 1 inRange: test1]);
STAssertTrue([bitfield countOfBit: 1 inRange: test2] == 0, @"Expected %@ to have 0 bits set in range %@, but got %lu", bitfield, NSStringFromRange(test2), (unsigned long)[bitfield countOfBit: 1 inRange: test2]);
STAssertTrue([bitfield countOfBit: 1 inRange: test3] == 8, @"Expected %@ to have 8 bits set in range %@, but got %lu", bitfield, NSStringFromRange(test3), (unsigned long)[bitfield countOfBit: 1 inRange: test3]);

NSRange before = NSMakeRange(0, setRange.location);
NSRange after = NSMakeRange(NSMaxRange(setRange), 20);

STAssertTrue([bitfield countOfBit: 1 inRange: before] == 0, @"Expected %@ to have no bits set in range %@, but got %lu", bitfield, NSStringFromRange(before), (unsigned long)[bitfield countOfBit: 1 inRange: before]);
STAssertTrue([bitfield countOfBit: 1 inRange: after] == 0, @"Expected %@ to have no bits set in range %@, but got %lu", bitfield, NSStringFromRange(before), (unsigned long)[bitfield countOfBit: 1 inRange: after]);
}

- (void) testSetBitsInRangeFrom64BitScalar
{
AQBitfield * bitfield = [AQBitfield new];

NSRange setRange = NSMakeRange(10, 64);
[bitfield setBitsInRange: setRange from64BitValue: 0xE000007FFF00FFFFull];

NSRange test1 = NSMakeRange(setRange.location, 16); // should be 16 bits set
NSRange test2 = NSMakeRange(setRange.location + 16, 8); // should be 0 bits set
NSRange test3 = NSMakeRange(setRange.location + 24, 8); // should be 8 bits set
NSRange test4 = NSMakeRange(setRange.location + 32, 8); // should be 7 bits set
NSRange test5 = NSMakeRange(setRange.location + 40, 16); // should be 0 bits set
NSRange test6 = NSMakeRange(setRange.location + 56, 8); // should be 3 bits set

STAssertTrue([bitfield countOfBit: 1 inRange: test1] == 16, @"Expected %@ to have 16 bits set in range %@, but got %lu", bitfield, NSStringFromRange(test1), (unsigned long)[bitfield countOfBit: 1 inRange: test1]);
STAssertTrue([bitfield countOfBit: 1 inRange: test2] == 0, @"Expected %@ to have 0 bits set in range %@, but got %lu", bitfield, NSStringFromRange(test2), (unsigned long)[bitfield countOfBit: 1 inRange: test2]);
STAssertTrue([bitfield countOfBit: 1 inRange: test3] == 8, @"Expected %@ to have 8 bits set in range %@, but got %lu", bitfield, NSStringFromRange(test3), (unsigned long)[bitfield countOfBit: 1 inRange: test3]);
STAssertTrue([bitfield countOfBit: 1 inRange: test4] == 7, @"Expected %@ to have 7 bits set in range %@, but got %lu", bitfield, NSStringFromRange(test3), (unsigned long)[bitfield countOfBit: 1 inRange: test4]);
STAssertTrue([bitfield countOfBit: 1 inRange: test5] == 0, @"Expected %@ to have 0 bits set in range %@, but got %lu", bitfield, NSStringFromRange(test3), (unsigned long)[bitfield countOfBit: 1 inRange: test5]);
STAssertTrue([bitfield countOfBit: 1 inRange: test6] == 3, @"Expected %@ to have 3 bits set in range %@, but got %lu", bitfield, NSStringFromRange(test3), (unsigned long)[bitfield countOfBit: 1 inRange: test6]);

NSRange before = NSMakeRange(0, setRange.location);
NSRange after = NSMakeRange(NSMaxRange(setRange), 20);

STAssertTrue([bitfield countOfBit: 1 inRange: before] == 0, @"Expected %@ to have no bits set in range %@, but got %lu", bitfield, NSStringFromRange(before), (unsigned long)[bitfield countOfBit: 1 inRange: before]);
STAssertTrue([bitfield countOfBit: 1 inRange: after] == 0, @"Expected %@ to have no bits set in range %@, but got %lu", bitfield, NSStringFromRange(before), (unsigned long)[bitfield countOfBit: 1 inRange: after]);
}

- (void) testBitCount
{
AQBitfield * bitfield = [AQBitfield new];
Expand Down

0 comments on commit 6c04370

Please sign in to comment.