Skip to content

Commit

Permalink
Implemented blocks-based predicates for matching against bitfields.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jim Dovey committed Jun 16, 2011
1 parent bc25888 commit 1755b9f
Show file tree
Hide file tree
Showing 9 changed files with 284 additions and 217 deletions.
32 changes: 12 additions & 20 deletions AQAppStateMachine.xcodeproj/project.pbxproj
Expand Up @@ -19,12 +19,9 @@
38431B8213A7C63B00178A7E /* AQBitfield.m in Sources */ = {isa = PBXBuildFile; fileRef = 38431B7F13A7C63B00178A7E /* AQBitfield.m */; };
38431B8413A7CCDC00178A7E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38431B8313A7CCDC00178A7E /* UIKit.framework */; };
38431B8513A7CCF100178A7E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38431B8313A7CCDC00178A7E /* UIKit.framework */; };
38431B8813A7F67900178A7E /* AQSimpleBitTestPredicate.h in Headers */ = {isa = PBXBuildFile; fileRef = 38431B8613A7F67900178A7E /* AQSimpleBitTestPredicate.h */; };
38431B8913A7F67900178A7E /* AQSimpleBitTestPredicate.m in Sources */ = {isa = PBXBuildFile; fileRef = 38431B8713A7F67900178A7E /* AQSimpleBitTestPredicate.m */; };
38431B8A13A7F67900178A7E /* AQSimpleBitTestPredicate.m in Sources */ = {isa = PBXBuildFile; fileRef = 38431B8713A7F67900178A7E /* AQSimpleBitTestPredicate.m */; };
38431B8D13A7FD9E00178A7E /* AQBitRangeMatchPredicate.h in Headers */ = {isa = PBXBuildFile; fileRef = 38431B8B13A7FD9E00178A7E /* AQBitRangeMatchPredicate.h */; };
38431B8E13A7FD9E00178A7E /* AQBitRangeMatchPredicate.m in Sources */ = {isa = PBXBuildFile; fileRef = 38431B8C13A7FD9E00178A7E /* AQBitRangeMatchPredicate.m */; };
38431B8F13A7FD9E00178A7E /* AQBitRangeMatchPredicate.m in Sources */ = {isa = PBXBuildFile; fileRef = 38431B8C13A7FD9E00178A7E /* AQBitRangeMatchPredicate.m */; };
38AC30BC13AA3D5C00AB071C /* AQBitfieldPredicates.h in Headers */ = {isa = PBXBuildFile; fileRef = 38AC30BA13AA3D5C00AB071C /* AQBitfieldPredicates.h */; };
38AC30BD13AA3D5C00AB071C /* AQBitfieldPredicates.m in Sources */ = {isa = PBXBuildFile; fileRef = 38AC30BB13AA3D5C00AB071C /* AQBitfieldPredicates.m */; };
38AC30BE13AA3D5C00AB071C /* AQBitfieldPredicates.m in Sources */ = {isa = PBXBuildFile; fileRef = 38AC30BB13AA3D5C00AB071C /* AQBitfieldPredicates.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -50,10 +47,8 @@
38431B7E13A7C63B00178A7E /* AQBitfield.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AQBitfield.h; sourceTree = "<group>"; };
38431B7F13A7C63B00178A7E /* AQBitfield.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AQBitfield.m; sourceTree = "<group>"; };
38431B8313A7CCDC00178A7E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
38431B8613A7F67900178A7E /* AQSimpleBitTestPredicate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AQSimpleBitTestPredicate.h; sourceTree = "<group>"; };
38431B8713A7F67900178A7E /* AQSimpleBitTestPredicate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AQSimpleBitTestPredicate.m; sourceTree = "<group>"; };
38431B8B13A7FD9E00178A7E /* AQBitRangeMatchPredicate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AQBitRangeMatchPredicate.h; sourceTree = "<group>"; };
38431B8C13A7FD9E00178A7E /* AQBitRangeMatchPredicate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AQBitRangeMatchPredicate.m; sourceTree = "<group>"; };
38AC30BA13AA3D5C00AB071C /* AQBitfieldPredicates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AQBitfieldPredicates.h; sourceTree = "<group>"; };
38AC30BB13AA3D5C00AB071C /* AQBitfieldPredicates.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AQBitfieldPredicates.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -114,10 +109,8 @@
children = (
38431B7E13A7C63B00178A7E /* AQBitfield.h */,
38431B7F13A7C63B00178A7E /* AQBitfield.m */,
38431B8613A7F67900178A7E /* AQSimpleBitTestPredicate.h */,
38431B8713A7F67900178A7E /* AQSimpleBitTestPredicate.m */,
38431B8B13A7FD9E00178A7E /* AQBitRangeMatchPredicate.h */,
38431B8C13A7FD9E00178A7E /* AQBitRangeMatchPredicate.m */,
38AC30BA13AA3D5C00AB071C /* AQBitfieldPredicates.h */,
38AC30BB13AA3D5C00AB071C /* AQBitfieldPredicates.m */,
38431B5A13A7C26800178A7E /* Supporting Files */,
);
path = AQAppStateMachine;
Expand Down Expand Up @@ -158,8 +151,7 @@
buildActionMask = 2147483647;
files = (
38431B8013A7C63B00178A7E /* AQBitfield.h in Headers */,
38431B8813A7F67900178A7E /* AQSimpleBitTestPredicate.h in Headers */,
38431B8D13A7FD9E00178A7E /* AQBitRangeMatchPredicate.h in Headers */,
38AC30BC13AA3D5C00AB071C /* AQBitfieldPredicates.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -259,8 +251,7 @@
buildActionMask = 2147483647;
files = (
38431B8113A7C63B00178A7E /* AQBitfield.m in Sources */,
38431B8913A7F67900178A7E /* AQSimpleBitTestPredicate.m in Sources */,
38431B8E13A7FD9E00178A7E /* AQBitRangeMatchPredicate.m in Sources */,
38AC30BD13AA3D5C00AB071C /* AQBitfieldPredicates.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -270,8 +261,7 @@
files = (
38431B7513A7C26900178A7E /* AQAppStateMachineTests.m in Sources */,
38431B8213A7C63B00178A7E /* AQBitfield.m in Sources */,
38431B8A13A7F67900178A7E /* AQSimpleBitTestPredicate.m in Sources */,
38431B8F13A7FD9E00178A7E /* AQBitRangeMatchPredicate.m in Sources */,
38AC30BE13AA3D5C00AB071C /* AQBitfieldPredicates.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -412,6 +402,7 @@
38431B7A13A7C26900178A7E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
38431B7B13A7C26900178A7E /* Build configuration list for PBXNativeTarget "AQAppStateMachineTests" */ = {
isa = XCConfigurationList;
Expand All @@ -420,6 +411,7 @@
38431B7D13A7C26900178A7E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
Expand Down
27 changes: 0 additions & 27 deletions AQAppStateMachine/AQBitRangeMatchPredicate.h

This file was deleted.

71 changes: 0 additions & 71 deletions AQAppStateMachine/AQBitRangeMatchPredicate.m

This file was deleted.

7 changes: 7 additions & 0 deletions AQAppStateMachine/AQBitfield.h
Expand Up @@ -17,6 +17,9 @@ typedef CFBit AQBit;

- (id) initWithSize: (NSUInteger) numberOfBits;

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

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

- (NSUInteger) countOfBit: (AQBit) bit inRange: (NSRange) range;
Expand All @@ -41,5 +44,9 @@ typedef CFBit AQBit;

// 'range' must be <= sizeof(NSUInteger), will compare least-significant bits of 'bits'
- (BOOL) bitsInRange: (NSRange) range matchBits: (NSUInteger) bits;
- (BOOL) bitsInRange: (NSRange) range equalToBitfield: (AQBitfield *) bitfield;

- (BOOL) bitsInRange: (NSRange) range maskedWith: (NSUInteger) mask matchBits: (NSUInteger) bits;
- (BOOL) bitsInRange: (NSRange) range maskedWith: (AQBitfield *) mask equalToBitfield: (AQBitfield *) bitfield;

@end
121 changes: 120 additions & 1 deletion AQAppStateMachine/AQBitfield.m
Expand Up @@ -86,6 +86,35 @@ - (id) mutableCopyWithZone:(NSZone *)zone
return ( [self copyWithZone: 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] );
}

- (NSUInteger) hash
{
return ( (NSUInteger)CFHash(_vector) );
}

- (BOOL) isEqual: (id) object
{
if ( [object isKindOfClass: [self class]] == NO )
return ( NO );

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

return ( (BOOL)CFEqual(_vector, other->_vector) );
}

- (NSUInteger) count
{
return ( (NSUInteger)CFBitVectorGetCount(_vector) );
Expand Down Expand Up @@ -186,7 +215,97 @@ - (BOOL) bitsInRange: (NSRange) range matchBits: (NSUInteger) bits

CFBitVectorGetBits(_vector, CFMakeRangeFromNS(range), vBytes);

return ( memcmp(vBytes, cBytes, sizeof(bits)) == 0 );
BOOL result = (memcmp(vBytes, cBytes, sizeof(bits)) == 0);
free(vBytes);

return ( result );
}

- (BOOL) bitsInRange: (NSRange) range equalToBitfield: (AQBitfield *) bitfield
{
NSParameterAssert(range.length == bitfield.count);
if ( range.length == 0 )
return ( NO );

UInt8 * vBytes = malloc(range.length);
bzero(vBytes, range.length);

UInt8 * cBytes = (UInt8 *)malloc(range.length);
bzero(cBytes, range.length);

CFBitVectorGetBits(_vector, CFMakeRangeFromNS(range), vBytes);
CFBitVectorGetBits(bitfield->_vector, CFRangeMake(0, bitfield.count), cBytes);

BOOL result = (memcmp(vBytes, cBytes, range.length) == 0);
free(vBytes);
free(cBytes);

return ( result );
}

- (BOOL) bitsInRange: (NSRange) range maskedWith: (NSUInteger) mask matchBits: (NSUInteger) bits
{
NSParameterAssert(range.length <= sizeof(NSUInteger));
if ( range.length == 0 )
return ( NO );

// mask the bits we're comparing against
bits &= mask;

NSUInteger swappedBits = CFSwapInt32HostToBig((uint32_t)bits);
NSUInteger swappedMask = CFSwapInt32HostToBig((uint32_t)mask);

UInt8 * vBytes = malloc(sizeof(bits));
bzero(vBytes, sizeof(bits));

// mask the bits we've pulled from the bitfield
NSUInteger *pCompareNum = (NSUInteger *)vBytes;
*pCompareNum &= swappedMask;

UInt8 * cBytes = (UInt8 *)&swappedBits;

CFBitVectorGetBits(_vector, CFMakeRangeFromNS(range), vBytes);

BOOL result = (memcmp(vBytes, cBytes, sizeof(bits)) == 0);
free(vBytes);

return ( result );
}

- (BOOL) bitsInRange: (NSRange) range maskedWith: (AQBitfield *) mask equalToBitfield: (AQBitfield *) bitfield
{
NSParameterAssert(range.length == bitfield.count);
NSParameterAssert(range.length == mask.count);
if ( range.length == 0 )
return ( NO );

int byteLen = (range.length + 7) / 8;
UInt8 * vBytes = malloc(range.length / sizeof(UInt8));
bzero(vBytes, range.length);

UInt8 * cBytes = (UInt8 *)malloc(range.length);
bzero(cBytes, range.length);

UInt8 * mBytes = malloc(range.length);
bzero(mBytes, range.length);

CFBitVectorGetBits(_vector, CFMakeRangeFromNS(range), vBytes);
CFBitVectorGetBits(bitfield->_vector, CFRangeMake(0, bitfield.count), cBytes);
CFBitVectorGetBits(mask->_vector, CFRangeMake(0, bitfield.count), mBytes);

// apply the mask to both ranges
for ( int i = 0; i < byteLen; i++ )
{
vBytes[i] &= mBytes[i];
cBytes[i] &= mBytes[i];
}

BOOL result = (memcmp(vBytes, cBytes, range.length) == 0);
free(vBytes);
free(cBytes);
free(mBytes);

return ( result );
}

@end

0 comments on commit 1755b9f

Please sign in to comment.