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