1*16467b97STreehugger Robot// [The "BSD licence"] 2*16467b97STreehugger Robot// Copyright (c) 2006-2007 Kay Roepke 2010 Alan Condit 3*16467b97STreehugger Robot// All rights reserved. 4*16467b97STreehugger Robot// 5*16467b97STreehugger Robot// Redistribution and use in source and binary forms, with or without 6*16467b97STreehugger Robot// modification, are permitted provided that the following conditions 7*16467b97STreehugger Robot// are met: 8*16467b97STreehugger Robot// 1. Redistributions of source code must retain the above copyright 9*16467b97STreehugger Robot// notice, this list of conditions and the following disclaimer. 10*16467b97STreehugger Robot// 2. Redistributions in binary form must reproduce the above copyright 11*16467b97STreehugger Robot// notice, this list of conditions and the following disclaimer in the 12*16467b97STreehugger Robot// documentation and/or other materials provided with the distribution. 13*16467b97STreehugger Robot// 3. The name of the author may not be used to endorse or promote products 14*16467b97STreehugger Robot// derived from this software without specific prior written permission. 15*16467b97STreehugger Robot// 16*16467b97STreehugger Robot// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17*16467b97STreehugger Robot// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18*16467b97STreehugger Robot// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19*16467b97STreehugger Robot// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20*16467b97STreehugger Robot// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21*16467b97STreehugger Robot// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22*16467b97STreehugger Robot// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23*16467b97STreehugger Robot// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24*16467b97STreehugger Robot// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25*16467b97STreehugger Robot// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26*16467b97STreehugger Robot 27*16467b97STreehugger Robot#import "ANTLRBitSet.h" 28*16467b97STreehugger Robot 29*16467b97STreehugger Robot@implementation ANTLRBitSet 30*16467b97STreehugger Robot#pragma mark Class Methods 31*16467b97STreehugger Robot 32*16467b97STreehugger Robot+ (ANTLRBitSet *) newBitSet 33*16467b97STreehugger Robot{ 34*16467b97STreehugger Robot return [[ANTLRBitSet alloc] init]; 35*16467b97STreehugger Robot} 36*16467b97STreehugger Robot 37*16467b97STreehugger Robot+ (ANTLRBitSet *) newBitSetWithType:(TokenType)type 38*16467b97STreehugger Robot{ 39*16467b97STreehugger Robot return [[ANTLRBitSet alloc] initWithType:type]; 40*16467b97STreehugger Robot} 41*16467b97STreehugger Robot 42*16467b97STreehugger Robot/** Construct a ANTLRBitSet given the size 43*16467b97STreehugger Robot * @param nbits The size of the ANTLRBitSet in bits 44*16467b97STreehugger Robot */ 45*16467b97STreehugger Robot+ (ANTLRBitSet *) newBitSetWithNBits:(NSUInteger)nbits 46*16467b97STreehugger Robot{ 47*16467b97STreehugger Robot return [[ANTLRBitSet alloc] initWithNBits:nbits]; 48*16467b97STreehugger Robot} 49*16467b97STreehugger Robot 50*16467b97STreehugger Robot+ (ANTLRBitSet *) newBitSetWithArray:(AMutableArray *)types 51*16467b97STreehugger Robot{ 52*16467b97STreehugger Robot return [[ANTLRBitSet alloc] initWithArrayOfBits:types]; 53*16467b97STreehugger Robot} 54*16467b97STreehugger Robot 55*16467b97STreehugger Robot+ (ANTLRBitSet *) newBitSetWithBits:(const unsigned long long *)theBits Count:(NSUInteger)longCount 56*16467b97STreehugger Robot{ 57*16467b97STreehugger Robot return [[ANTLRBitSet alloc] initWithBits:theBits Count:longCount]; 58*16467b97STreehugger Robot} 59*16467b97STreehugger Robot 60*16467b97STreehugger Robot 61*16467b97STreehugger Robot+ (ANTLRBitSet *) of:(NSUInteger) el 62*16467b97STreehugger Robot{ 63*16467b97STreehugger Robot ANTLRBitSet *s = [ANTLRBitSet newBitSetWithNBits:(el + 1)]; 64*16467b97STreehugger Robot [s add:el]; 65*16467b97STreehugger Robot return s; 66*16467b97STreehugger Robot} 67*16467b97STreehugger Robot 68*16467b97STreehugger Robot+ (ANTLRBitSet *) of:(NSUInteger) a And2:(NSUInteger) b 69*16467b97STreehugger Robot{ 70*16467b97STreehugger Robot NSInteger c = (((a>b)?a:b)+1); 71*16467b97STreehugger Robot ANTLRBitSet *s = [ANTLRBitSet newBitSetWithNBits:c]; 72*16467b97STreehugger Robot [s add:a]; 73*16467b97STreehugger Robot [s add:b]; 74*16467b97STreehugger Robot return s; 75*16467b97STreehugger Robot} 76*16467b97STreehugger Robot 77*16467b97STreehugger Robot+ (ANTLRBitSet *) of:(NSUInteger)a And2:(NSUInteger)b And3:(NSUInteger)c 78*16467b97STreehugger Robot{ 79*16467b97STreehugger Robot NSUInteger d = ((a>b)?a:b); 80*16467b97STreehugger Robot d = ((c>d)?c:d)+1; 81*16467b97STreehugger Robot ANTLRBitSet *s = [ANTLRBitSet newBitSetWithNBits:d]; 82*16467b97STreehugger Robot [s add:a]; 83*16467b97STreehugger Robot [s add:b]; 84*16467b97STreehugger Robot [s add:c]; 85*16467b97STreehugger Robot return s; 86*16467b97STreehugger Robot} 87*16467b97STreehugger Robot 88*16467b97STreehugger Robot+ (ANTLRBitSet *) of:(NSUInteger)a And2:(NSUInteger)b And3:(NSUInteger)c And4:(NSUInteger)d 89*16467b97STreehugger Robot{ 90*16467b97STreehugger Robot NSUInteger e = ((a>b)?a:b); 91*16467b97STreehugger Robot NSUInteger f = ((c>d)?c:d); 92*16467b97STreehugger Robot e = ((e>f)?e:f)+1; 93*16467b97STreehugger Robot ANTLRBitSet *s = [ANTLRBitSet newBitSetWithNBits:e]; 94*16467b97STreehugger Robot [s add:a]; 95*16467b97STreehugger Robot [s add:b]; 96*16467b97STreehugger Robot [s add:c]; 97*16467b97STreehugger Robot [s add:d]; 98*16467b97STreehugger Robot return s; 99*16467b97STreehugger Robot} 100*16467b97STreehugger Robot 101*16467b97STreehugger Robot// initializer 102*16467b97STreehugger Robot#pragma mark Initializer 103*16467b97STreehugger Robot 104*16467b97STreehugger Robot- (ANTLRBitSet *) init 105*16467b97STreehugger Robot{ 106*16467b97STreehugger Robot if ((self = [super init]) != nil) { 107*16467b97STreehugger Robot bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault,0); 108*16467b97STreehugger Robot } 109*16467b97STreehugger Robot return self; 110*16467b97STreehugger Robot} 111*16467b97STreehugger Robot 112*16467b97STreehugger Robot- (ANTLRBitSet *) initWithType:(TokenType)type 113*16467b97STreehugger Robot{ 114*16467b97STreehugger Robot if ((self = [super init]) != nil) { 115*16467b97STreehugger Robot bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault,0); 116*16467b97STreehugger Robot if ((CFIndex)type >= CFBitVectorGetCount(bitVector)) 117*16467b97STreehugger Robot CFBitVectorSetCount(bitVector, type+1); 118*16467b97STreehugger Robot CFBitVectorSetBitAtIndex(bitVector, type, 1); 119*16467b97STreehugger Robot } 120*16467b97STreehugger Robot return self; 121*16467b97STreehugger Robot} 122*16467b97STreehugger Robot 123*16467b97STreehugger Robot- (ANTLRBitSet *) initWithNBits:(NSUInteger)nbits 124*16467b97STreehugger Robot{ 125*16467b97STreehugger Robot if ((self = [super init]) != nil) { 126*16467b97STreehugger Robot bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault,0); 127*16467b97STreehugger Robot CFBitVectorSetCount( bitVector, nbits ); 128*16467b97STreehugger Robot } 129*16467b97STreehugger Robot return self; 130*16467b97STreehugger Robot} 131*16467b97STreehugger Robot 132*16467b97STreehugger Robot- (ANTLRBitSet *) initWithBitVector:(CFMutableBitVectorRef)theBitVector 133*16467b97STreehugger Robot{ 134*16467b97STreehugger Robot if ((self = [super init]) != nil) { 135*16467b97STreehugger Robot bitVector = theBitVector; 136*16467b97STreehugger Robot } 137*16467b97STreehugger Robot return self; 138*16467b97STreehugger Robot} 139*16467b97STreehugger Robot 140*16467b97STreehugger Robot// Initialize the bit vector with a constant array of ulonglongs like ANTLR generates. 141*16467b97STreehugger Robot// Converts to big endian, because the underlying CFBitVector works like that. 142*16467b97STreehugger Robot- (ANTLRBitSet *) initWithBits:(const unsigned long long *)theBits Count:(NSUInteger)longCount 143*16467b97STreehugger Robot{ 144*16467b97STreehugger Robot if ((self = [super init]) != nil) { 145*16467b97STreehugger Robot unsigned int longNo; 146*16467b97STreehugger Robot// unsigned long long swappedBits = 0LL; 147*16467b97STreehugger Robot CFIndex bitIdx; 148*16467b97STreehugger Robot bitVector = CFBitVectorCreateMutable ( kCFAllocatorDefault, 0 ); 149*16467b97STreehugger Robot CFBitVectorSetCount( bitVector, sizeof(unsigned long long)*8*longCount ); 150*16467b97STreehugger Robot 151*16467b97STreehugger Robot for (longNo = 0; longNo < longCount; longNo++) { 152*16467b97STreehugger Robot for (bitIdx = 0; bitIdx < (CFIndex)sizeof(unsigned long long)*8; bitIdx++) { 153*16467b97STreehugger Robot// swappedBits = CFSwapInt64HostToBig(theBits[longNo]); 154*16467b97STreehugger Robot// if (swappedBits & (1LL << bitIdx)) { 155*16467b97STreehugger Robot if (theBits[longNo] & (1LL << bitIdx)) { 156*16467b97STreehugger Robot CFBitVectorSetBitAtIndex(bitVector, bitIdx+(longNo*(sizeof(unsigned long long)*8)), 1); 157*16467b97STreehugger Robot } 158*16467b97STreehugger Robot } 159*16467b97STreehugger Robot } 160*16467b97STreehugger Robot } 161*16467b97STreehugger Robot return self; 162*16467b97STreehugger Robot} 163*16467b97STreehugger Robot 164*16467b97STreehugger Robot// Initialize bit vector with an array of anything. Just test the boolValue and set the corresponding bit. 165*16467b97STreehugger Robot// Note: This is big-endian! 166*16467b97STreehugger Robot- (ANTLRBitSet *) initWithArrayOfBits:(NSArray *)theArray 167*16467b97STreehugger Robot{ 168*16467b97STreehugger Robot if ((self = [super init]) != nil) { 169*16467b97STreehugger Robot bitVector = CFBitVectorCreateMutable ( kCFAllocatorDefault, 0 ); 170*16467b97STreehugger Robot id value; 171*16467b97STreehugger Robot int bit = 0; 172*16467b97STreehugger Robot for (value in theArray) { 173*16467b97STreehugger Robot if ([value boolValue] == YES) { 174*16467b97STreehugger Robot [self add:bit]; 175*16467b97STreehugger Robot //CFBitVectorSetBitAtIndex(bitVector, bit, 1); 176*16467b97STreehugger Robot } 177*16467b97STreehugger Robot bit++; 178*16467b97STreehugger Robot } 179*16467b97STreehugger Robot } 180*16467b97STreehugger Robot return self; 181*16467b97STreehugger Robot} 182*16467b97STreehugger Robot 183*16467b97STreehugger Robot- (void)dealloc 184*16467b97STreehugger Robot{ 185*16467b97STreehugger Robot#ifdef DEBUG_DEALLOC 186*16467b97STreehugger Robot NSLog( @"called dealloc in ANTLRBitSet" ); 187*16467b97STreehugger Robot#endif 188*16467b97STreehugger Robot CFRelease(bitVector); 189*16467b97STreehugger Robot [super dealloc]; 190*16467b97STreehugger Robot} 191*16467b97STreehugger Robot 192*16467b97STreehugger Robot // operations 193*16467b97STreehugger Robot#pragma mark Operations 194*16467b97STreehugger Robot// return a copy of (self|aBitSet) 195*16467b97STreehugger Robot- (ANTLRBitSet *) or:(ANTLRBitSet *) aBitSet 196*16467b97STreehugger Robot{ 197*16467b97STreehugger Robot ANTLRBitSet *bitsetCopy = [self mutableCopyWithZone:nil]; 198*16467b97STreehugger Robot [bitsetCopy orInPlace:aBitSet]; 199*16467b97STreehugger Robot return bitsetCopy; 200*16467b97STreehugger Robot} 201*16467b97STreehugger Robot 202*16467b97STreehugger Robot// perform a bitwise OR operation in place by changing underlying bit vector, growing it if necessary 203*16467b97STreehugger Robot- (void) orInPlace:(ANTLRBitSet *) aBitSet 204*16467b97STreehugger Robot{ 205*16467b97STreehugger Robot CFIndex selfCnt = CFBitVectorGetCount(bitVector); 206*16467b97STreehugger Robot CFMutableBitVectorRef otherBitVector = [aBitSet _bitVector]; 207*16467b97STreehugger Robot CFIndex otherCnt = CFBitVectorGetCount(otherBitVector); 208*16467b97STreehugger Robot CFIndex maxBitCnt = selfCnt > otherCnt ? selfCnt : otherCnt; 209*16467b97STreehugger Robot CFBitVectorSetCount(bitVector,maxBitCnt); // be sure to grow the CFBitVector manually! 210*16467b97STreehugger Robot 211*16467b97STreehugger Robot CFIndex currIdx; 212*16467b97STreehugger Robot for (currIdx = 0; currIdx < maxBitCnt; currIdx++) { 213*16467b97STreehugger Robot if (CFBitVectorGetBitAtIndex(bitVector, currIdx) | CFBitVectorGetBitAtIndex(otherBitVector, currIdx)) { 214*16467b97STreehugger Robot CFBitVectorSetBitAtIndex(bitVector, currIdx, 1); 215*16467b97STreehugger Robot } 216*16467b97STreehugger Robot } 217*16467b97STreehugger Robot} 218*16467b97STreehugger Robot 219*16467b97STreehugger Robot// set a bit, grow the bit vector if necessary 220*16467b97STreehugger Robot- (void) add:(NSUInteger) bit 221*16467b97STreehugger Robot{ 222*16467b97STreehugger Robot if ((CFIndex)bit >= CFBitVectorGetCount(bitVector)) 223*16467b97STreehugger Robot CFBitVectorSetCount(bitVector, bit+1); 224*16467b97STreehugger Robot CFBitVectorSetBitAtIndex(bitVector, bit, 1); 225*16467b97STreehugger Robot} 226*16467b97STreehugger Robot 227*16467b97STreehugger Robot// unset a bit 228*16467b97STreehugger Robot- (void) remove:(NSUInteger) bit 229*16467b97STreehugger Robot{ 230*16467b97STreehugger Robot CFBitVectorSetBitAtIndex(bitVector, bit, 0); 231*16467b97STreehugger Robot} 232*16467b97STreehugger Robot 233*16467b97STreehugger Robot- (void) setAllBits:(BOOL) aState 234*16467b97STreehugger Robot{ 235*16467b97STreehugger Robot for( NSInteger bit=0; bit < CFBitVectorGetCount(bitVector); bit++ ) { 236*16467b97STreehugger Robot CFBitVectorSetBitAtIndex(bitVector, bit, aState); 237*16467b97STreehugger Robot } 238*16467b97STreehugger Robot} 239*16467b97STreehugger Robot 240*16467b97STreehugger Robot// returns the number of bits in the bit vector. 241*16467b97STreehugger Robot- (NSInteger) numBits 242*16467b97STreehugger Robot{ 243*16467b97STreehugger Robot // return CFBitVectorGetCount(bitVector); 244*16467b97STreehugger Robot return CFBitVectorGetCountOfBit(bitVector, CFRangeMake(0, CFBitVectorGetCount(bitVector)), 1); 245*16467b97STreehugger Robot} 246*16467b97STreehugger Robot 247*16467b97STreehugger Robot// returns the number of bits in the bit vector. 248*16467b97STreehugger Robot- (NSUInteger) size 249*16467b97STreehugger Robot{ 250*16467b97STreehugger Robot return CFBitVectorGetCount(bitVector); 251*16467b97STreehugger Robot} 252*16467b97STreehugger Robot 253*16467b97STreehugger Robot- (void) setSize:(NSUInteger) nBits 254*16467b97STreehugger Robot{ 255*16467b97STreehugger Robot CFBitVectorSetCount( bitVector, nBits ); 256*16467b97STreehugger Robot} 257*16467b97STreehugger Robot 258*16467b97STreehugger Robot#pragma mark Informational 259*16467b97STreehugger Robot// return a bitmask representation of this bitvector for easy operations 260*16467b97STreehugger Robot- (unsigned long long) bitMask:(NSUInteger) bitNumber 261*16467b97STreehugger Robot{ 262*16467b97STreehugger Robot return 1LL << bitNumber; 263*16467b97STreehugger Robot} 264*16467b97STreehugger Robot 265*16467b97STreehugger Robot// test a bit (no pun intended) 266*16467b97STreehugger Robot- (BOOL) member:(NSUInteger) bitNumber 267*16467b97STreehugger Robot{ 268*16467b97STreehugger Robot return CFBitVectorGetBitAtIndex(bitVector,bitNumber) ? YES : NO; 269*16467b97STreehugger Robot} 270*16467b97STreehugger Robot 271*16467b97STreehugger Robot// are all bits off? 272*16467b97STreehugger Robot- (BOOL) isNil 273*16467b97STreehugger Robot{ 274*16467b97STreehugger Robot return ((CFBitVectorGetCountOfBit(bitVector, CFRangeMake(0,CFBitVectorGetCount(bitVector)), 1) == 0) ? YES : NO); 275*16467b97STreehugger Robot} 276*16467b97STreehugger Robot 277*16467b97STreehugger Robot// debugging aid. GDB invokes this automagically 278*16467b97STreehugger Robot// return a string representation of the bit vector, indicating by their bitnumber which bits are set 279*16467b97STreehugger Robot- (NSString *) description 280*16467b97STreehugger Robot{ 281*16467b97STreehugger Robot CFIndex length = CFBitVectorGetCount(bitVector); 282*16467b97STreehugger Robot CFIndex currBit; 283*16467b97STreehugger Robot NSMutableString *descString = [NSMutableString stringWithString:@"{"]; 284*16467b97STreehugger Robot BOOL haveInsertedBit = NO; 285*16467b97STreehugger Robot for (currBit = 0; currBit < length; currBit++) { 286*16467b97STreehugger Robot if ( CFBitVectorGetBitAtIndex(bitVector, currBit) ) { 287*16467b97STreehugger Robot if (haveInsertedBit) { 288*16467b97STreehugger Robot [descString appendString:@","]; 289*16467b97STreehugger Robot } 290*16467b97STreehugger Robot [descString appendFormat:@"%d", currBit]; 291*16467b97STreehugger Robot haveInsertedBit = YES; 292*16467b97STreehugger Robot } 293*16467b97STreehugger Robot } 294*16467b97STreehugger Robot [descString appendString:@"}"]; 295*16467b97STreehugger Robot return descString; 296*16467b97STreehugger Robot} 297*16467b97STreehugger Robot 298*16467b97STreehugger Robot// return a string representation of the bit vector, indicating by their bitnumber which bits are set 299*16467b97STreehugger Robot- (NSString *) toString 300*16467b97STreehugger Robot{ 301*16467b97STreehugger Robot 302*16467b97STreehugger Robot return [self description]; 303*16467b97STreehugger Robot} 304*16467b97STreehugger Robot 305*16467b97STreehugger Robot // NSCopying 306*16467b97STreehugger Robot#pragma mark NSCopying support 307*16467b97STreehugger Robot 308*16467b97STreehugger Robot- (id) mutableCopyWithZone:(NSZone *) theZone 309*16467b97STreehugger Robot{ 310*16467b97STreehugger Robot ANTLRBitSet *newBitSet = [[ANTLRBitSet allocWithZone:theZone] initWithBitVector:CFBitVectorCreateMutableCopy(kCFAllocatorDefault,0,bitVector)]; 311*16467b97STreehugger Robot return newBitSet; 312*16467b97STreehugger Robot} 313*16467b97STreehugger Robot 314*16467b97STreehugger Robot- (CFMutableBitVectorRef) _bitVector 315*16467b97STreehugger Robot{ 316*16467b97STreehugger Robot return bitVector; 317*16467b97STreehugger Robot} 318*16467b97STreehugger Robot 319*16467b97STreehugger Robot@synthesize bitVector; 320*16467b97STreehugger Robot@end 321*16467b97STreehugger Robot 322*16467b97STreehugger RobotNSInteger max(NSInteger a, NSInteger b) 323*16467b97STreehugger Robot{ 324*16467b97STreehugger Robot return (a>b)?a:b; 325*16467b97STreehugger Robot} 326*16467b97STreehugger Robot 327