mirror of https://github.com/status-im/qzxing.git
149 lines
3.7 KiB
C++
149 lines
3.7 KiB
C++
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
|
/*
|
|
* BitArray.cpp
|
|
* zxing
|
|
*
|
|
* 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>
|
|
#include <iostream>
|
|
#include <limits>
|
|
|
|
using namespace std;
|
|
|
|
namespace zxing {
|
|
|
|
static unsigned int logDigits(unsigned digits) {
|
|
unsigned log = 0;
|
|
unsigned val = 1;
|
|
while (val < digits) {
|
|
log++;
|
|
val <<= 1;
|
|
}
|
|
return log;
|
|
}
|
|
|
|
const unsigned int BitArray::bitsPerWord_ = numeric_limits<unsigned int>::digits;
|
|
const unsigned int BitArray::logBits_ = logDigits(bitsPerWord_);
|
|
const unsigned int BitArray::bitsMask_ = (1 << logBits_) - 1;
|
|
|
|
size_t BitArray::wordsForBits(size_t bits) {
|
|
int arraySize = bits >> logBits_;
|
|
if (bits - (arraySize << logBits_) != 0) {
|
|
arraySize++;
|
|
}
|
|
return arraySize;
|
|
}
|
|
|
|
BitArray::BitArray(size_t size) :
|
|
size_(size), bits_(wordsForBits(size), (const unsigned int)0) {
|
|
}
|
|
|
|
BitArray::~BitArray() {
|
|
}
|
|
|
|
size_t BitArray::getSize() {
|
|
return size_;
|
|
}
|
|
|
|
void BitArray::setBulk(size_t i, unsigned int newBits) {
|
|
bits_[i >> logBits_] = newBits;
|
|
}
|
|
|
|
void BitArray::setRange(int start, int end) {
|
|
if (end < start) {
|
|
throw IllegalArgumentException("invalid call to BitArray::setRange");
|
|
}
|
|
if (end == start) {
|
|
return;
|
|
}
|
|
end--; // will be easier to treat this as the last actually set bit -- inclusive
|
|
int firstInt = start >> 5;
|
|
int lastInt = end >> 5;
|
|
for (int i = firstInt; i <= lastInt; i++) {
|
|
int firstBit = i > firstInt ? 0 : start & 0x1F;
|
|
int lastBit = i < lastInt ? 31 : end & 0x1F;
|
|
int mask;
|
|
if (firstBit == 0 && lastBit == 31) {
|
|
mask = -1;
|
|
} else {
|
|
mask = 0;
|
|
for (int j = firstBit; j <= lastBit; j++) {
|
|
mask |= 1 << j;
|
|
}
|
|
}
|
|
bits_[i] |= mask;
|
|
}
|
|
}
|
|
|
|
void BitArray::clear() {
|
|
size_t max = bits_.size();
|
|
for (size_t i = 0; i < max; i++) {
|
|
bits_[i] = 0;
|
|
}
|
|
}
|
|
|
|
bool BitArray::isRange(size_t start, size_t end, bool value) {
|
|
if (end < start) {
|
|
throw IllegalArgumentException("end must be after start");
|
|
}
|
|
if (end == start) {
|
|
return true;
|
|
}
|
|
// treat the 'end' as inclusive, rather than exclusive
|
|
end--;
|
|
size_t firstWord = start >> logBits_;
|
|
size_t lastWord = end >> logBits_;
|
|
for (size_t i = firstWord; i <= lastWord; i++) {
|
|
size_t firstBit = i > firstWord ? 0 : start & bitsMask_;
|
|
size_t lastBit = i < lastWord ? bitsPerWord_ - 1: end & bitsMask_;
|
|
unsigned int mask;
|
|
if (firstBit == 0 && lastBit == bitsPerWord_ - 1) {
|
|
mask = numeric_limits<unsigned int>::max();
|
|
} else {
|
|
mask = 0;
|
|
for (size_t j = firstBit; j <= lastBit; j++) {
|
|
mask |= 1 << j;
|
|
}
|
|
}
|
|
if (value) {
|
|
if ((bits_[i] & mask) != mask) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if ((bits_[i] & mask) != 0) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
vector<unsigned int>& BitArray::getBitArray() {
|
|
return bits_;
|
|
}
|
|
|
|
void BitArray::reverse() {
|
|
std::vector<unsigned int> newBits(bits_.size(),(const unsigned int) 0);
|
|
for (size_t i = 0; i < size_; i++) {
|
|
if (get(size_ - i - 1)) {
|
|
newBits[i >> logBits_] |= 1<< (i & bitsMask_);
|
|
}
|
|
}
|
|
bits_ = newBits;
|
|
}
|
|
}
|