2011-11-16 15:40:46 +02:00
|
|
|
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
|
|
|
/*
|
|
|
|
* Copyright 2010 ZXing authors. All rights reserved.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <zxing/common/BitArray.h>
|
|
|
|
|
2013-07-03 20:44:10 +03:00
|
|
|
using std::vector;
|
|
|
|
using zxing::BitArray;
|
2011-11-16 15:40:46 +02:00
|
|
|
|
2013-07-03 20:44:10 +03:00
|
|
|
// VC++
|
|
|
|
using zxing::Ref;
|
2011-11-16 15:40:46 +02:00
|
|
|
|
2013-07-03 20:44:10 +03:00
|
|
|
int BitArray::makeArraySize(int size) {
|
|
|
|
return (size + bitsPerWord-1) >> logBits;
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
|
|
|
|
2013-07-03 20:44:10 +03:00
|
|
|
BitArray::BitArray(int size_)
|
|
|
|
: size(size_), bits(makeArraySize(size)) {}
|
2011-11-16 15:40:46 +02:00
|
|
|
|
|
|
|
BitArray::~BitArray() {
|
|
|
|
}
|
|
|
|
|
2013-07-03 20:44:10 +03:00
|
|
|
int BitArray::getSize() const {
|
|
|
|
return size;
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
|
|
|
|
2013-07-03 20:44:10 +03:00
|
|
|
void BitArray::setBulk(int i, int newBits) {
|
|
|
|
bits[i >> logBits] = newBits;
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
|
|
|
|
2013-07-03 20:44:10 +03:00
|
|
|
void BitArray::clear() {
|
|
|
|
int max = bits->size();
|
|
|
|
for (int i = 0; i < max; i++) {
|
|
|
|
bits[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BitArray::isRange(int start, int end, bool value) {
|
2011-11-16 15:40:46 +02:00
|
|
|
if (end < start) {
|
2013-07-03 20:44:10 +03:00
|
|
|
throw IllegalArgumentException();
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
|
|
|
if (end == start) {
|
2013-07-03 20:44:10 +03:00
|
|
|
return true; // empty range matches
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
|
|
|
end--; // will be easier to treat this as the last actually set bit -- inclusive
|
2013-07-03 20:44:10 +03:00
|
|
|
int firstInt = start >> logBits;
|
|
|
|
int lastInt = end >> logBits;
|
2011-11-16 15:40:46 +02:00
|
|
|
for (int i = firstInt; i <= lastInt; i++) {
|
2013-07-03 20:44:10 +03:00
|
|
|
int firstBit = i > firstInt ? 0 : start & bitsMask;
|
|
|
|
int lastBit = i < lastInt ? (bitsPerWord-1) : end & bitsMask;
|
2011-11-16 15:40:46 +02:00
|
|
|
int mask;
|
2013-07-03 20:44:10 +03:00
|
|
|
if (firstBit == 0 && lastBit == (bitsPerWord-1)) {
|
2011-11-16 15:40:46 +02:00
|
|
|
mask = -1;
|
|
|
|
} else {
|
|
|
|
mask = 0;
|
|
|
|
for (int j = firstBit; j <= lastBit; j++) {
|
|
|
|
mask |= 1 << j;
|
|
|
|
}
|
|
|
|
}
|
2013-07-03 20:44:10 +03:00
|
|
|
|
|
|
|
// 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 false;
|
|
|
|
}
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
2013-07-03 20:44:10 +03:00
|
|
|
return true;
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
|
|
|
|
2013-07-03 20:44:10 +03:00
|
|
|
vector<int>& BitArray::getBitArray() {
|
|
|
|
return bits->values();
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
|
|
|
|
2013-07-03 20:44:10 +03:00
|
|
|
void BitArray::reverse() {
|
|
|
|
ArrayRef<int> newBits(bits->size());
|
|
|
|
int size = this->size;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
if (get(size - i - 1)) {
|
|
|
|
newBits[i >> logBits] |= 1 << (i & bitsMask);
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
|
|
|
}
|
2013-07-03 20:44:10 +03:00
|
|
|
bits = newBits;
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
|
|
|
|
2013-07-03 20:44:10 +03:00
|
|
|
BitArray::Reverse::Reverse(Ref<BitArray> array_) : array(array_) {
|
|
|
|
array->reverse();
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
|
|
|
|
2013-07-03 20:44:10 +03:00
|
|
|
BitArray::Reverse::~Reverse() {
|
|
|
|
array->reverse();
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
// N.B.: This only works for 32 bit ints ...
|
|
|
|
int numberOfTrailingZeros(int i) {
|
|
|
|
// HD, Figure 5-14
|
|
|
|
int y;
|
|
|
|
if (i == 0) return 32;
|
|
|
|
int 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 - (((unsigned int)(i << 1)) >> 31);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int BitArray::getNextSet(int from) {
|
|
|
|
if (from >= size) {
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
int bitsOffset = from >> logBits;
|
|
|
|
int currentBits = bits[bitsOffset];
|
|
|
|
// mask off lesser bits first
|
|
|
|
currentBits &= ~((1 << (from & bitsMask)) - 1);
|
|
|
|
while (currentBits == 0) {
|
|
|
|
if (++bitsOffset == (int)bits->size()) {
|
|
|
|
return size;
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
2013-07-03 20:44:10 +03:00
|
|
|
currentBits = bits[bitsOffset];
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
2013-07-03 20:44:10 +03:00
|
|
|
int result = (bitsOffset << logBits) + numberOfTrailingZeros(currentBits);
|
|
|
|
return result > size ? size : result;
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|
2013-07-03 20:44:10 +03:00
|
|
|
|
|
|
|
int BitArray::getNextUnset(int from) {
|
|
|
|
if (from >= size) {
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
int bitsOffset = from >> logBits;
|
|
|
|
int currentBits = ~bits[bitsOffset];
|
|
|
|
// mask off lesser bits first
|
|
|
|
currentBits &= ~((1 << (from & bitsMask)) - 1);
|
|
|
|
while (currentBits == 0) {
|
|
|
|
if (++bitsOffset == (int)bits->size()) {
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
currentBits = ~bits[bitsOffset];
|
|
|
|
}
|
|
|
|
int result = (bitsOffset << logBits) + numberOfTrailingZeros(currentBits);
|
|
|
|
return result > size ? size : result;
|
2011-11-16 15:40:46 +02:00
|
|
|
}
|