123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- /*
- * Copyright 2012 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- #import "ZXBitArray.h"
- #import "ZXByteArray.h"
- #import "ZXIntArray.h"
-
- @interface ZXBitArray ()
-
- @property (nonatomic, assign) int32_t *bits;
- @property (nonatomic, assign) int bitsLength;
- @property (nonatomic, assign) int size;
-
- @end
-
- @implementation ZXBitArray
-
- - (id)init {
- if (self = [super init]) {
- _size = 0;
- _bits = (int32_t *)calloc(1, sizeof(int32_t));
- _bitsLength = 1;
- }
-
- return self;
- }
-
- // For testing only
- - (id)initWithBits:(ZXIntArray *)bits size:(int)size {
- if (self = [self initWithSize:size]) {
- _bits = bits.array;
- _bits = (int32_t *)malloc(bits.length * sizeof(int32_t));
- memcpy(_bits, bits.array, bits.length * sizeof(int32_t));
- _bitsLength = bits.length;
- }
-
- return self;
- }
-
- - (id)initWithSize:(int)size {
- if (self = [super init]) {
- _size = size;
- _bitsLength = (size + 31) / 32;
- _bits = (int32_t *)calloc(_bitsLength, sizeof(int32_t));
- }
-
- return self;
- }
-
- - (void)dealloc {
- if (_bits != NULL) {
- free(_bits);
- _bits = NULL;
- }
- }
-
- - (int)sizeInBytes {
- return (self.size + 7) / 8;
- }
-
- - (void)ensureCapacity:(int)size {
- if (size > self.bitsLength * 32) {
- int newBitsLength = (size + 31) / 32;
- self.bits = realloc(self.bits, newBitsLength * sizeof(int32_t));
- memset(self.bits + self.bitsLength, 0, (newBitsLength - self.bitsLength) * sizeof(int32_t));
-
- self.bitsLength = newBitsLength;
- }
- }
-
- - (BOOL)get:(int)i {
- return (_bits[i / 32] & (1 << (i & 0x1F))) != 0;
- }
-
- - (void)set:(int)i {
- _bits[i / 32] |= 1 << (i & 0x1F);
- }
-
- - (void)flip:(int)i {
- _bits[i / 32] ^= 1 << (i & 0x1F);
- }
-
- - (int)nextSet:(int)from {
- if (from >= self.size) {
- return self.size;
- }
- int bitsOffset = from / 32;
- int32_t currentBits = self.bits[bitsOffset];
- // mask off lesser bits first
- currentBits &= ~((1 << (from & 0x1F)) - 1);
- while (currentBits == 0) {
- if (++bitsOffset == self.bitsLength) {
- return self.size;
- }
- currentBits = self.bits[bitsOffset];
- }
- int result = (bitsOffset * 32) + [self numberOfTrailingZeros:currentBits];
- return result > self.size ? self.size : result;
- }
-
- - (int)nextUnset:(int)from {
- if (from >= self.size) {
- return self.size;
- }
- int bitsOffset = from / 32;
- int32_t currentBits = ~self.bits[bitsOffset];
- // mask off lesser bits first
- currentBits &= ~((1 << (from & 0x1F)) - 1);
- while (currentBits == 0) {
- if (++bitsOffset == self.bitsLength) {
- return self.size;
- }
- currentBits = ~self.bits[bitsOffset];
- }
- int result = (bitsOffset * 32) + [self numberOfTrailingZeros:currentBits];
- return result > self.size ? self.size : result;
- }
-
- - (void)setBulk:(int)i newBits:(int32_t)newBits {
- _bits[i / 32] = newBits;
- }
-
- - (void)setRange:(int)start end:(int)end {
- if (end < start) {
- @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Start greater than end" userInfo:nil];
- }
- if (end == start) {
- return;
- }
- end--; // will be easier to treat this as the last actually set bit -- inclusive
- int firstInt = start / 32;
- int lastInt = end / 32;
- for (int i = firstInt; i <= lastInt; i++) {
- int firstBit = i > firstInt ? 0 : start & 0x1F;
- int lastBit = i < lastInt ? 31 : end & 0x1F;
- int32_t mask;
- if (lastBit > 31) {
- @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Bit-shift operand does not support more than 31 bits" userInfo:nil];
- }
- if (firstBit == 0 && lastBit == 31) {
- mask = -1;
- } else {
- mask = 0;
- for (int j = firstBit; j <= lastBit; j++) {
- mask |= 1 << j;
- }
- }
- _bits[i] |= mask;
- }
- }
-
- - (void)clear {
- memset(self.bits, 0, self.bitsLength * sizeof(int32_t));
- }
-
- - (BOOL)isRange:(int)start end:(int)end value:(BOOL)value {
- if (end < start) {
- @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Start greater than end" userInfo:nil];
- }
- if (end == start) {
- return YES; // empty range matches
- }
- end--; // will be easier to treat this as the last actually set bit -- inclusive
- int firstInt = start / 32;
- int lastInt = end / 32;
- for (int i = firstInt; i <= lastInt; i++) {
- int firstBit = i > firstInt ? 0 : start & 0x1F;
- int lastBit = i < lastInt ? 31 : end & 0x1F;
- int32_t mask;
- if (lastBit > 31) {
- @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Bit-shift operand does not support more than 31 bits" userInfo:nil];
- }
- if (firstBit == 0 && lastBit == 31) {
- mask = -1;
- } else {
- mask = 0;
- for (int j = firstBit; j <= lastBit; j++) {
- mask |= 1 << j;
- }
- }
-
- // Return false if we're looking for 1s and the masked bits[i] isn't all 1s (that is,
- // equals the mask, or we're looking for 0s and the masked portion is not all 0s
- if ((_bits[i] & mask) != (value ? mask : 0)) {
- return NO;
- }
- }
-
- return YES;
- }
-
- - (void)appendBit:(BOOL)bit {
- [self ensureCapacity:self.size + 1];
- if (bit) {
- self.bits[self.size / 32] |= 1 << (self.size & 0x1F);
- }
- self.size++;
- }
-
- - (void)appendBits:(int32_t)value numBits:(int)numBits {
- if (numBits < 0 || numBits > 32) {
- @throw [NSException exceptionWithName:NSInvalidArgumentException
- reason:@"Num bits must be between 0 and 32"
- userInfo:nil];
- }
- [self ensureCapacity:self.size + numBits];
- for (int numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--) {
- [self appendBit:((value >> (numBitsLeft - 1)) & 0x01) == 1];
- }
- }
-
- - (void)appendBitArray:(ZXBitArray *)other {
- int otherSize = [other size];
- [self ensureCapacity:self.size + otherSize];
-
- for (int i = 0; i < otherSize; i++) {
- [self appendBit:[other get:i]];
- }
- }
-
- - (void)xor:(ZXBitArray *)other {
- if (self.bitsLength != other.bitsLength) {
- @throw [NSException exceptionWithName:NSInvalidArgumentException
- reason:@"Sizes don't match"
- userInfo:nil];
- }
-
- for (int i = 0; i < self.bitsLength; i++) {
- // The last byte could be incomplete (i.e. not have 8 bits in
- // it) but there is no problem since 0 XOR 0 == 0.
- self.bits[i] ^= other.bits[i];
- }
- }
-
- - (void)toBytes:(int)bitOffset array:(ZXByteArray *)array offset:(int)offset numBytes:(int)numBytes {
- for (int i = 0; i < numBytes; i++) {
- int32_t theByte = 0;
- for (int j = 0; j < 8; j++) {
- if ([self get:bitOffset]) {
- theByte |= 1 << (7 - j);
- }
- bitOffset++;
- }
- array.array[offset + i] = (int8_t) theByte;
- }
- }
-
- - (ZXIntArray *)bitArray {
- ZXIntArray *array = [[ZXIntArray alloc] initWithLength:self.bitsLength];
- memcpy(array.array, self.bits, array.length * sizeof(int32_t));
- return array;
- }
-
- - (BOOL)isEqual:(id)o {
- if (![o isKindOfClass:[ZXBitArray class]]) {
- return NO;
- }
- ZXBitArray *other = (ZXBitArray *)o;
- return self.size == other.size && memcmp(self.bits, other.bits, self.bitsLength) != 0;
- }
-
- - (NSUInteger)hash {
- return 31 * self.size;
- }
-
- - (void)reverse {
- int32_t *newBits = (int32_t *)calloc(self.bitsLength, sizeof(int32_t));
- int size = self.size;
-
- // reverse all int's first
- int len = ((size-1) / 32);
- int oldBitsLen = len + 1;
- for (int i = 0; i < oldBitsLen; i++) {
- long x = (long) self.bits[i];
- x = ((x >> 1) & 0x55555555L) | ((x & 0x55555555L) << 1);
- x = ((x >> 2) & 0x33333333L) | ((x & 0x33333333L) << 2);
- x = ((x >> 4) & 0x0f0f0f0fL) | ((x & 0x0f0f0f0fL) << 4);
- x = ((x >> 8) & 0x00ff00ffL) | ((x & 0x00ff00ffL) << 8);
- x = ((x >> 16) & 0x0000ffffL) | ((x & 0x0000ffffL) << 16);
- newBits[len - i] = (int32_t) x;
- }
- // now correct the int's if the bit size isn't a multiple of 32
- if (size != oldBitsLen * 32) {
- int leftOffset = oldBitsLen * 32 - size;
- int mask = 1;
- for (int i = 0; i < 31 - leftOffset; i++) {
- mask = (mask << 1) | 1;
- }
- int32_t currentInt = (newBits[0] >> leftOffset) & mask;
- for (int i = 1; i < oldBitsLen; i++) {
- int32_t nextInt = newBits[i];
- currentInt |= nextInt << (32 - leftOffset);
- newBits[i - 1] = currentInt;
- currentInt = (nextInt >> leftOffset) & mask;
- }
- newBits[oldBitsLen - 1] = currentInt;
- }
- if (self.bits != NULL) {
- free(self.bits);
- }
- self.bits = newBits;
- }
-
- - (NSString *)description {
- NSMutableString *result = [NSMutableString string];
-
- for (int i = 0; i < self.size; i++) {
- if ((i & 0x07) == 0) {
- [result appendString:@" "];
- }
- [result appendString:[self get:i] ? @"X" : @"."];
- }
-
- return result;
- }
-
- // Ported from OpenJDK Integer.numberOfTrailingZeros implementation
- - (int32_t)numberOfTrailingZeros:(int32_t)i {
- int32_t y;
- if (i == 0) return 32;
- int32_t n = 31;
- y = i <<16; if (y != 0) { n = n -16; i = y; }
- y = i << 8; if (y != 0) { n = n - 8; i = y; }
- y = i << 4; if (y != 0) { n = n - 4; i = y; }
- y = i << 2; if (y != 0) { n = n - 2; i = y; }
- return n - (int32_t)((uint32_t)(i << 1) >> 31);
- }
-
- - (id)copyWithZone:(NSZone *)zone {
- ZXBitArray *copy = [[ZXBitArray allocWithZone:zone] initWithSize:self.size];
- memcpy(copy.bits, self.bits, self.size * sizeof(int32_t));
- return copy;
- }
-
- @end
|