File indexing completed on 2024-06-23 05:48:48

0001 /*
0002     This file is part of the Okteta Kasten module, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2009, 2022 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "modsum16bytearraychecksumalgorithm.hpp"
0010 
0011 // Okteta core
0012 #include <Okteta/AbstractByteArrayModel>
0013 // KF
0014 #include <KConfigGroup>
0015 #include <KLocalizedString>
0016 // Qt
0017 #include <QtEndian>
0018 
0019 static constexpr char ModSum16ConfigGroupId[] = "ModularSum16";
0020 
0021 ModSum16ByteArrayChecksumAlgorithm::ModSum16ByteArrayChecksumAlgorithm()
0022     : AbstractByteArrayChecksumAlgorithm(
0023         i18nc("name of the checksum algorithm", "Modular sum 16-bit"),
0024         QStringLiteral("ModularSum16")
0025       )
0026 {}
0027 
0028 ModSum16ByteArrayChecksumAlgorithm::~ModSum16ByteArrayChecksumAlgorithm() = default;
0029 
0030 AbstractByteArrayChecksumParameterSet* ModSum16ByteArrayChecksumAlgorithm::parameterSet() { return &mParameterSet; }
0031 
0032 void ModSum16ByteArrayChecksumAlgorithm::loadConfig(const KConfigGroup& configGroup)
0033 {
0034     const KConfigGroup algorithmConfigGroup = configGroup.group(ModSum16ConfigGroupId);
0035 
0036     mParameterSet.loadConfig(algorithmConfigGroup);
0037 }
0038 
0039 void ModSum16ByteArrayChecksumAlgorithm::saveConfig(KConfigGroup& configGroup) const
0040 {
0041     KConfigGroup algorithmConfigGroup = configGroup.group(ModSum16ConfigGroupId);
0042 
0043     mParameterSet.saveConfig(algorithmConfigGroup);
0044 }
0045 
0046 bool ModSum16ByteArrayChecksumAlgorithm::calculateChecksum(QString* result,
0047                                                            const Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range) const
0048 {
0049     const bool useLittleEndian = (mParameterSet.endianness() == QSysInfo::LittleEndian);
0050     quint16 modSum = useLittleEndian ?
0051                      calculateModSumWithLittleEndian(model, range) :
0052                      calculateModSumWithBigEndian(model, range);
0053 
0054     modSum = ~modSum + 1;
0055 
0056     if (useLittleEndian) {
0057         modSum = qbswap(modSum);
0058     }
0059 
0060     *result = QStringLiteral("%1").arg(modSum, 4, 16, QChar::fromLatin1('0'));
0061     return true;
0062 }
0063 
0064 quint16 ModSum16ByteArrayChecksumAlgorithm::calculateModSumWithBigEndian(const Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range) const
0065 {
0066     quint16 modSum = 0x0000;
0067     Okteta::Address nextBlockEnd = range.start() + CalculatedByteCountSignalLimit;
0068 
0069     // TODO: move padding checks into extra code before and after loop
0070     for (Okteta::Address i = range.start(); i <= range.end(); ++i) {
0071         quint16 value = (quint16)((quint8)(model->byte(i))) << 8;
0072         ++i;
0073         if (i <= range.end()) {
0074             value |= (quint16)((quint8)(model->byte(i)));
0075         }
0076 
0077         modSum += value;
0078 #if 0
0079         const uchar value = (crcBits & 0xFF) + model->byte(i);
0080         crcBits >>= 8;
0081         crcBits ^= lookupTable[value];
0082 #endif
0083         if (i >= nextBlockEnd) {
0084             nextBlockEnd += CalculatedByteCountSignalLimit;
0085             Q_EMIT calculatedBytes(range.localIndex(i) + 1);
0086         }
0087     }
0088 
0089     return modSum;
0090 }
0091 
0092 quint16 ModSum16ByteArrayChecksumAlgorithm::calculateModSumWithLittleEndian(const Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range) const
0093 {
0094     quint16 modSum = 0x0000;
0095     Okteta::Address nextBlockEnd = range.start() + CalculatedByteCountSignalLimit;
0096 
0097     // TODO: move padding checks into extra code before and after loop
0098     for (Okteta::Address i = range.start(); i <= range.end(); ++i) {
0099         quint16 value = (quint16)((quint8)(model->byte(i)));
0100         ++i;
0101         if (i <= range.end()) {
0102             value |= (quint16)((quint8)(model->byte(i))) << 8;
0103         }
0104 
0105         modSum += value;
0106 
0107         if (i >= nextBlockEnd) {
0108             nextBlockEnd += CalculatedByteCountSignalLimit;
0109             Q_EMIT calculatedBytes(range.localIndex(i) + 1);
0110         }
0111     }
0112 
0113     return modSum;
0114 }
0115 
0116 #include "moc_modsum16bytearraychecksumalgorithm.cpp"