File: QRDataBlock.cpp

package info (click to toggle)
zxing-cpp 2.3.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 26,832 kB
  • sloc: cpp: 32,803; ansic: 18,360; php: 1,156; python: 215; makefile: 28; sh: 3
file content (92 lines) | stat: -rw-r--r-- 3,228 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
* Copyright 2016 Nu-book Inc.
* Copyright 2016 ZXing authors
*/
// SPDX-License-Identifier: Apache-2.0

#include "QRDataBlock.h"

#include "QRErrorCorrectionLevel.h"
#include "QRVersion.h"
#include "ZXAlgorithms.h"

namespace ZXing::QRCode {

std::vector<DataBlock> DataBlock::GetDataBlocks(const ByteArray& rawCodewords, const Version& version, ErrorCorrectionLevel ecLevel)
{
	if (Size(rawCodewords) != version.totalCodewords())
		return {};

	// Figure out the number and size of data blocks used by this version and
	// error correction level
	auto& ecBlocks = version.ecBlocksForLevel(ecLevel);

	// First count the total number of data blocks
	int totalBlocks = ecBlocks.numBlocks();
	if (totalBlocks == 0)
		return {};

	std::vector<DataBlock> result(totalBlocks);
	// Now establish DataBlocks of the appropriate size and number of data codewords
	int numResultBlocks = 0;
	for (auto& ecBlock : ecBlocks.blockArray()) {
		for (int i = 0; i < ecBlock.count; i++) {
			auto& item = result[numResultBlocks++];
			item._numDataCodewords = ecBlock.dataCodewords;
			item._codewords.resize(ecBlocks.codewordsPerBlock + ecBlock.dataCodewords);
		}
	}

	// 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 = Size(result[0]._codewords);
	int longerBlocksStartAt = Size(result) - 1;
	while (longerBlocksStartAt >= 0) {
		int numCodewords = Size(result[longerBlocksStartAt]._codewords);
		if (numCodewords == shorterBlocksTotalCodewords) {
			break;
		}
		longerBlocksStartAt--;
	}
	longerBlocksStartAt++;

	int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.codewordsPerBlock;
	// The last elements of result may be 1 element longer;
	// first fill out as many elements as all of them have
	int rawCodewordsOffset = 0;
	if (version.isModel1()) {
		// in Model 1 symbols the data blocks are concatenated back to back
		for (int j = 0; j < numResultBlocks; j++)
			for (int i = 0; i < shorterBlocksNumDataCodewords; i++)
				result[j]._codewords[i] = rawCodewords[rawCodewordsOffset++];
	} else {
		// in all others, the data blocks are interleaved
		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 = Size(result[0]._codewords);
	if (version.isModel1()) {
		for (int j = 0; j < numResultBlocks; j++) {
			for (int i = shorterBlocksNumDataCodewords; i < max; i++) {
				int iOffset = j < longerBlocksStartAt ? i : i + 1;
				result[j]._codewords[iOffset] = rawCodewords[rawCodewordsOffset++];
			}
		}
	} else {
		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++];
			}
		}
	}
	return result;
}

} // namespace ZXing::QRCode