mirror of
https://github.com/status-im/qzxing.git
synced 2025-02-08 17:15:04 +00:00
119 lines
4.0 KiB
C++
119 lines
4.0 KiB
C++
|
/*
|
||
|
* DataBlock.cpp
|
||
|
* zxing
|
||
|
*
|
||
|
* Created by Christian Brunschen on 19/05/2008.
|
||
|
* Copyright 2008 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/qrcode/decoder/DataBlock.h>
|
||
|
#include <zxing/common/IllegalArgumentException.h>
|
||
|
|
||
|
namespace zxing {
|
||
|
namespace qrcode {
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
DataBlock::DataBlock(int numDataCodewords, ArrayRef<unsigned char> codewords) :
|
||
|
numDataCodewords_(numDataCodewords), codewords_(codewords) {
|
||
|
}
|
||
|
|
||
|
int DataBlock::getNumDataCodewords() {
|
||
|
return numDataCodewords_;
|
||
|
}
|
||
|
|
||
|
ArrayRef<unsigned char> DataBlock::getCodewords() {
|
||
|
return codewords_;
|
||
|
}
|
||
|
|
||
|
|
||
|
std::vector<Ref<DataBlock> > DataBlock::getDataBlocks(ArrayRef<unsigned char> rawCodewords, Version *version,
|
||
|
ErrorCorrectionLevel &ecLevel) {
|
||
|
|
||
|
|
||
|
// Figure out the number and size of data blocks used by this version and
|
||
|
// error correction level
|
||
|
ECBlocks &ecBlocks = version->getECBlocksForLevel(ecLevel);
|
||
|
|
||
|
|
||
|
// First count the total number of data blocks
|
||
|
int totalBlocks = 0;
|
||
|
vector<ECB*> ecBlockArray = ecBlocks.getECBlocks();
|
||
|
for (size_t i = 0; i < ecBlockArray.size(); i++) {
|
||
|
totalBlocks += ecBlockArray[i]->getCount();
|
||
|
}
|
||
|
|
||
|
// Now establish DataBlocks of the appropriate size and number of data codewords
|
||
|
std::vector<Ref<DataBlock> > result(totalBlocks);
|
||
|
int numResultBlocks = 0;
|
||
|
for (size_t j = 0; j < ecBlockArray.size(); j++) {
|
||
|
ECB *ecBlock = ecBlockArray[j];
|
||
|
for (int i = 0; i < ecBlock->getCount(); i++) {
|
||
|
int numDataCodewords = ecBlock->getDataCodewords();
|
||
|
int numBlockCodewords = ecBlocks.getECCodewords() + numDataCodewords;
|
||
|
ArrayRef<unsigned char> buffer(numBlockCodewords);
|
||
|
Ref<DataBlock> blockRef(new DataBlock(numDataCodewords, buffer));
|
||
|
result[numResultBlocks++] = blockRef;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// All blocks have the same amount of data, except that the last n
|
||
|
// (where n may be 0) have 1 more byte. Figure out where these start.
|
||
|
int shorterBlocksTotalCodewords = result[0]->codewords_.size();
|
||
|
int longerBlocksStartAt = result.size() - 1;
|
||
|
while (longerBlocksStartAt >= 0) {
|
||
|
int numCodewords = result[longerBlocksStartAt]->codewords_.size();
|
||
|
if (numCodewords == shorterBlocksTotalCodewords) {
|
||
|
break;
|
||
|
}
|
||
|
if (numCodewords != shorterBlocksTotalCodewords + 1) {
|
||
|
throw IllegalArgumentException("Data block sizes differ by more than 1");
|
||
|
}
|
||
|
longerBlocksStartAt--;
|
||
|
}
|
||
|
longerBlocksStartAt++;
|
||
|
|
||
|
int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewords();
|
||
|
// The last elements of result may be 1 element longer;
|
||
|
// first fill out as many elements as all of them have
|
||
|
int rawCodewordsOffset = 0;
|
||
|
for (int i = 0; i < shorterBlocksNumDataCodewords; i++) {
|
||
|
for (int j = 0; j < numResultBlocks; j++) {
|
||
|
result[j]->codewords_[i] = rawCodewords[rawCodewordsOffset++];
|
||
|
}
|
||
|
}
|
||
|
// Fill out the last data block in the longer ones
|
||
|
for (int j = longerBlocksStartAt; j < numResultBlocks; j++) {
|
||
|
result[j]->codewords_[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];
|
||
|
}
|
||
|
// Now add in error correction blocks
|
||
|
int max = result[0]->codewords_.size();
|
||
|
for (int i = shorterBlocksNumDataCodewords; i < max; i++) {
|
||
|
for (int j = 0; j < numResultBlocks; j++) {
|
||
|
int iOffset = j < longerBlocksStartAt ? i : i + 1;
|
||
|
result[j]->codewords_[iOffset] = rawCodewords[rawCodewordsOffset++];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((size_t)rawCodewordsOffset != rawCodewords.size()) {
|
||
|
throw IllegalArgumentException("rawCodewordsOffset != rawCodewords.length");
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|