1 /*
2     This file is part of the Okteta Kasten module, made within the KDE community.
3 
4     SPDX-FileCopyrightText: 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7 */
8 
9 #include "crc32bytearraychecksumalgorithm.hpp"
10 
11 // Okteta core
12 #include <Okteta/AbstractByteArrayModel>
13 // KF
14 #include <KLocalizedString>
15 
16 class Crc32LookupTable
17 {
18 public:
19     Crc32LookupTable();
20 
21 public:
22     const quint32& operator[](int i) const;
23 
24 private:
25     static quint32 reverseBits(quint32 bits, char bitCount);
26 
27 private:
28     quint32 mTable[256];
29 };
30 
Crc32LookupTable()31 Crc32LookupTable::Crc32LookupTable()
32 {
33     quint32 polynomial = 0x04c11db7;
34 
35     // 256 values representing ASCII character codes.
36     for (int i = 0; i < 256; ++i) {
37         int value = reverseBits(i, 8) << 24;
38         for (int j = 0; j < 8; ++j) {
39             const bool hasMsb = (value & (1 << 31));
40             value <<= 1;
41             if (hasMsb) {
42                 value ^= polynomial;
43             }
44         }
45 
46         mTable[i] = reverseBits(value, 32);
47     }
48 }
49 
reverseBits(quint32 bits,char bitCount)50 quint32 Crc32LookupTable::reverseBits(quint32 bits, char bitCount)
51 {
52     quint32 result = 0;
53     for (int i = 1; i <= bitCount; ++i) {
54         if (bits & 0x01) {
55             result |= (1 << (bitCount - i));
56         }
57         bits >>= 1;
58     }
59 
60     return result;
61 }
62 
operator [](int i) const63 inline const quint32& Crc32LookupTable::operator[](int i) const { return mTable[i]; }
64 
Crc32ByteArrayChecksumAlgorithm()65 Crc32ByteArrayChecksumAlgorithm::Crc32ByteArrayChecksumAlgorithm()
66     : AbstractByteArrayChecksumAlgorithm(
67         i18nc("name of the checksum algorithm, Cyclic Redundancy Check 32", "CRC-32"))
68 {}
69 
70 Crc32ByteArrayChecksumAlgorithm::~Crc32ByteArrayChecksumAlgorithm() = default;
71 
parameterSet()72 AbstractByteArrayChecksumParameterSet* Crc32ByteArrayChecksumAlgorithm::parameterSet() { return &mParameterSet; }
73 
calculateChecksum(QString * result,const Okteta::AbstractByteArrayModel * model,const Okteta::AddressRange & range) const74 bool Crc32ByteArrayChecksumAlgorithm::calculateChecksum(QString* result,
75                                                         const Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range) const
76 {
77     Crc32LookupTable lookupTable;
78     quint32 crcBits = 0xffffffff;
79     Okteta::Address nextBlockEnd = range.start() + CalculatedByteCountSignalLimit;
80     for (Okteta::Address i = range.start(); i <= range.end(); ++i) {
81         const uchar value = (crcBits & 0xFF) ^ model->byte(i);
82         crcBits >>= 8;
83         crcBits ^= lookupTable[value];
84 
85         if (i >= nextBlockEnd) {
86             nextBlockEnd += CalculatedByteCountSignalLimit;
87             emit calculatedBytes(range.localIndex(i) + 1);
88         }
89     }
90 
91     crcBits ^= 0xffffffff;
92 
93     *result = QStringLiteral("%1").arg(crcBits, 8, 16, QChar::fromLatin1('0'));
94 
95     return true;
96 }
97